1# Copyright 2012-2017 The Meson development team
2
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6
7#     http://www.apache.org/licenses/LICENSE-2.0
8
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import copy
16import functools
17import os.path
18import typing as T
19
20from .. import coredata
21from .. import mlog
22from ..mesonlib import MesonException, MachineChoice, version_compare
23
24from ..linkers import LinkerEnvVarsMixin
25from .compilers import (
26    gnu_winlibs,
27    msvc_winlibs,
28    Compiler,
29)
30from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES
31from .mixins.clike import CLikeCompiler
32from .mixins.ccrx import CcrxCompiler
33from .mixins.c2000 import C2000Compiler
34from .mixins.arm import ArmCompiler, ArmclangCompiler
35from .mixins.visualstudio import MSVCCompiler, ClangClCompiler
36from .mixins.gnu import GnuCompiler
37from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler
38from .mixins.clang import ClangCompiler
39from .mixins.elbrus import ElbrusCompiler
40from .mixins.pgi import PGICompiler
41from .mixins.emscripten import EmscriptenMixin
42
43if T.TYPE_CHECKING:
44    from ..envconfig import MachineInfo
45
46
47def non_msvc_eh_options(eh, args):
48    if eh == 'none':
49        args.append('-fno-exceptions')
50    elif eh == 's' or eh == 'c':
51        mlog.warning('non-MSVC compilers do not support ' + eh + ' exception handling.' +
52                     'You may want to set eh to \'default\'.')
53
54class CPPCompiler(CLikeCompiler, Compiler):
55
56    @classmethod
57    def attribute_check_func(cls, name):
58        try:
59            return CXX_FUNC_ATTRIBUTES.get(name, C_FUNC_ATTRIBUTES[name])
60        except KeyError:
61            raise MesonException('Unknown function attribute "{}"'.format(name))
62
63    language = 'cpp'
64
65    def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool,
66                 info: 'MachineInfo', exe_wrap: T.Optional[str] = None, **kwargs):
67        # If a child ObjCPP class has already set it, don't set it ourselves
68        Compiler.__init__(self, exelist, version, for_machine, info, **kwargs)
69        CLikeCompiler.__init__(self, is_cross, exe_wrap)
70
71    @staticmethod
72    def get_display_language():
73        return 'C++'
74
75    def get_no_stdinc_args(self):
76        return ['-nostdinc++']
77
78    def sanity_check(self, work_dir, environment):
79        code = 'class breakCCompiler;int main(void) { return 0; }\n'
80        return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code)
81
82    def get_compiler_check_args(self):
83        # -fpermissive allows non-conforming code to compile which is necessary
84        # for many C++ checks. Particularly, the has_header_symbol check is
85        # too strict without this and always fails.
86        return super().get_compiler_check_args() + ['-fpermissive']
87
88    def has_header_symbol(self, hname, symbol, prefix, env, *, extra_args=None, dependencies=None):
89        # Check if it's a C-like symbol
90        found, cached = super().has_header_symbol(hname, symbol, prefix, env,
91                                                  extra_args=extra_args,
92                                                  dependencies=dependencies)
93        if found:
94            return True, cached
95        # Check if it's a class or a template
96        if extra_args is None:
97            extra_args = []
98        fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol}
99        t = '''{prefix}
100        #include <{header}>
101        using {symbol};
102        int main(void) {{ return 0; }}'''
103        return self.compiles(t.format(**fargs), env, extra_args=extra_args,
104                             dependencies=dependencies)
105
106    def _test_cpp_std_arg(self, cpp_std_value):
107        # Test whether the compiler understands a -std=XY argument
108        assert(cpp_std_value.startswith('-std='))
109
110        # This test does not use has_multi_arguments() for two reasons:
111        # 1. has_multi_arguments() requires an env argument, which the compiler
112        #    object does not have at this point.
113        # 2. even if it did have an env object, that might contain another more
114        #    recent -std= argument, which might lead to a cascaded failure.
115        CPP_TEST = 'int i = static_cast<int>(0);'
116        with self.compile(CPP_TEST, extra_args=[cpp_std_value], mode='compile') as p:
117            if p.returncode == 0:
118                mlog.debug('Compiler accepts {}:'.format(cpp_std_value), 'YES')
119                return True
120            else:
121                mlog.debug('Compiler accepts {}:'.format(cpp_std_value), 'NO')
122                return False
123
124    @functools.lru_cache()
125    def _find_best_cpp_std(self, cpp_std):
126        # The initial version mapping approach to make falling back
127        # from '-std=c++14' to '-std=c++1y' was too brittle. For instance,
128        # Apple's Clang uses a different versioning scheme to upstream LLVM,
129        # making the whole detection logic awfully brittle. Instead, let's
130        # just see if feeding GCC or Clang our '-std=' setting works, and
131        # if not, try the fallback argument.
132        CPP_FALLBACKS = {
133            'c++11': 'c++0x',
134            'gnu++11': 'gnu++0x',
135            'c++14': 'c++1y',
136            'gnu++14': 'gnu++1y',
137            'c++17': 'c++1z',
138            'gnu++17': 'gnu++1z'
139        }
140
141        # Currently, remapping is only supported for Clang, Elbrus and GCC
142        assert(self.id in frozenset(['clang', 'lcc', 'gcc', 'emscripten']))
143
144        if cpp_std not in CPP_FALLBACKS:
145            # 'c++03' and 'c++98' don't have fallback types
146            return '-std=' + cpp_std
147
148        for i in (cpp_std, CPP_FALLBACKS[cpp_std]):
149            cpp_std_value = '-std=' + i
150            if self._test_cpp_std_arg(cpp_std_value):
151                return cpp_std_value
152
153        raise MesonException('C++ Compiler does not support -std={}'.format(cpp_std))
154
155
156class ClangCPPCompiler(ClangCompiler, CPPCompiler):
157    def __init__(self, exelist, version, for_machine: MachineChoice,
158                 is_cross, info: 'MachineInfo', exe_wrapper=None,
159                 defines : T.Optional[T.List[str]] = None, **kwargs):
160        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
161                             info, exe_wrapper, **kwargs)
162        ClangCompiler.__init__(self, defines)
163        default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
164        self.warn_args = {'0': [],
165                          '1': default_warn_args,
166                          '2': default_warn_args + ['-Wextra'],
167                          '3': default_warn_args + ['-Wextra', '-Wpedantic']}
168
169    def get_options(self):
170        opts = CPPCompiler.get_options(self)
171        opts.update({
172            'eh': coredata.UserComboOption(
173                'C++ exception handling type.',
174                ['none', 'default', 'a', 's', 'sc'],
175                'default',
176            ),
177            'rtti': coredata.UserBooleanOption('Enable RTTI', True),
178            'std': coredata.UserComboOption(
179                'C++ language standard to use',
180                ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
181                 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
182                'none',
183            ),
184        })
185        if self.info.is_windows() or self.info.is_cygwin():
186            opts.update({
187                'winlibs': coredata.UserArrayOption(
188                    'Standard Win libraries to link against',
189                    gnu_winlibs,
190                ),
191            })
192        return opts
193
194    def get_option_compile_args(self, options):
195        args = []
196        std = options['std']
197        if std.value != 'none':
198            args.append(self._find_best_cpp_std(std.value))
199
200        non_msvc_eh_options(options['eh'].value, args)
201
202        if not options['rtti'].value:
203            args.append('-fno-rtti')
204
205        return args
206
207    def get_option_link_args(self, options):
208        if self.info.is_windows() or self.info.is_cygwin():
209            return options['winlibs'].value[:]
210        return []
211
212    def language_stdlib_only_link_flags(self):
213        return ['-lstdc++']
214
215
216class AppleClangCPPCompiler(ClangCPPCompiler):
217    def language_stdlib_only_link_flags(self):
218        return ['-lc++']
219
220
221class EmscriptenCPPCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCPPCompiler):
222    def __init__(self, exelist, version, for_machine: MachineChoice,
223                 is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs):
224        if not is_cross:
225            raise MesonException('Emscripten compiler can only be used for cross compilation.')
226        ClangCPPCompiler.__init__(self, exelist=exelist, version=version,
227                                  for_machine=for_machine, is_cross=is_cross,
228                                  info=info, exe_wrapper=exe_wrapper, **kwargs)
229        self.id = 'emscripten'
230
231    def get_option_compile_args(self, options):
232        args = []
233        std = options['std']
234        if std.value != 'none':
235            args.append(self._find_best_cpp_std(std.value))
236        return args
237
238
239class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
240    def __init__(self, exelist, version, for_machine: MachineChoice,
241                 is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
242        CPPCompiler.__init__(self, exelist=exelist, version=version,
243                                  for_machine=for_machine, is_cross=is_cross,
244                                  info=info, exe_wrapper=exe_wrapper, **kwargs)
245        ArmclangCompiler.__init__(self)
246        default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
247        self.warn_args = {'0': [],
248                          '1': default_warn_args,
249                          '2': default_warn_args + ['-Wextra'],
250                          '3': default_warn_args + ['-Wextra', '-Wpedantic']}
251
252    def get_options(self):
253        opts = CPPCompiler.get_options(self)
254        opts.update({
255            'eh': coredata.UserComboOption(
256                'C++ exception handling type.',
257                ['none', 'default', 'a', 's', 'sc'],
258                'default',
259            ),
260            'std': coredata.UserComboOption(
261                'C++ language standard to use',
262                [
263                    'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17',
264                    'gnu++98', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17',
265                ],
266                'none',
267            ),
268        })
269        return opts
270
271    def get_option_compile_args(self, options):
272        args = []
273        std = options['std']
274        if std.value != 'none':
275            args.append('-std=' + std.value)
276
277        non_msvc_eh_options(options['eh'].value, args)
278
279        return args
280
281    def get_option_link_args(self, options):
282        return []
283
284
285class GnuCPPCompiler(GnuCompiler, CPPCompiler):
286    def __init__(self, exelist, version, for_machine: MachineChoice,
287                 is_cross, info: 'MachineInfo', exe_wrap, defines, **kwargs):
288        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrap, **kwargs)
289        GnuCompiler.__init__(self, defines)
290        default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
291        self.warn_args = {'0': [],
292                          '1': default_warn_args,
293                          '2': default_warn_args + ['-Wextra'],
294                          '3': default_warn_args + ['-Wextra', '-Wpedantic']}
295
296    def get_options(self):
297        opts = CPPCompiler.get_options(self)
298        opts.update({
299            'eh': coredata.UserComboOption(
300                'C++ exception handling type.',
301                ['none', 'default', 'a', 's', 'sc'],
302                'default',
303            ),
304            'rtti': coredata.UserBooleanOption('Enable RTTI', True),
305            'std': coredata.UserComboOption(
306                'C++ language standard to use',
307                ['none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
308                'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a'],
309                'none',
310            ),
311            'debugstl': coredata.UserBooleanOption(
312                'STL debug mode',
313                False,
314            )
315        })
316        if self.info.is_windows() or self.info.is_cygwin():
317            opts.update({
318                'winlibs': coredata.UserArrayOption(
319                    'Standard Win libraries to link against',
320                    gnu_winlibs,
321                ),
322            })
323        return opts
324
325    def get_option_compile_args(self, options):
326        args = []
327        std = options['std']
328        if std.value != 'none':
329            args.append(self._find_best_cpp_std(std.value))
330
331        non_msvc_eh_options(options['eh'].value, args)
332
333        if not options['rtti'].value:
334            args.append('-fno-rtti')
335
336        if options['debugstl'].value:
337            args.append('-D_GLIBCXX_DEBUG=1')
338        return args
339
340    def get_option_link_args(self, options):
341        if self.info.is_windows() or self.info.is_cygwin():
342            return options['winlibs'].value[:]
343        return []
344
345    def get_pch_use_args(self, pch_dir, header):
346        return ['-fpch-preprocess', '-include', os.path.basename(header)]
347
348    def language_stdlib_only_link_flags(self):
349        return ['-lstdc++']
350
351
352class PGICPPCompiler(PGICompiler, CPPCompiler):
353    def __init__(self, exelist, version, for_machine: MachineChoice,
354                 is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
355        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrapper, **kwargs)
356        PGICompiler.__init__(self)
357
358
359class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
360    def __init__(self, exelist, version, for_machine: MachineChoice,
361                 is_cross, info: 'MachineInfo', exe_wrapper=None,
362                 defines=None, **kwargs):
363        GnuCPPCompiler.__init__(self, exelist, version, for_machine,
364                                is_cross, info, exe_wrapper, defines,
365                                **kwargs)
366        ElbrusCompiler.__init__(self)
367
368    # It does not support c++/gnu++ 17 and 1z, but still does support 0x, 1y, and gnu++98.
369    def get_options(self):
370        opts = CPPCompiler.get_options(self)
371        opts.update({
372            'eh': coredata.UserComboOption(
373                'C++ exception handling type.',
374                ['none', 'default', 'a', 's', 'sc'],
375                'default',
376            ),
377            'std': coredata.UserComboOption(
378                'C++ language standard to use',
379                [
380                    'none', 'c++98', 'c++03', 'c++0x', 'c++11', 'c++14', 'c++1y',
381                    'gnu++98', 'gnu++03', 'gnu++0x', 'gnu++11', 'gnu++14', 'gnu++1y',
382                ],
383                'none',
384            ),
385            'debugstl': coredata.UserBooleanOption(
386                'STL debug mode',
387                False,
388            ),
389        })
390        return opts
391
392    # Elbrus C++ compiler does not have lchmod, but there is only linker warning, not compiler error.
393    # So we should explicitly fail at this case.
394    def has_function(self, funcname, prefix, env, *, extra_args=None, dependencies=None):
395        if funcname == 'lchmod':
396            return False, False
397        else:
398            return super().has_function(funcname, prefix, env,
399                                        extra_args=extra_args,
400                                        dependencies=dependencies)
401
402    # Elbrus C++ compiler does not support RTTI, so don't check for it.
403    def get_option_compile_args(self, options):
404        args = []
405        std = options['std']
406        if std.value != 'none':
407            args.append(self._find_best_cpp_std(std.value))
408
409        non_msvc_eh_options(options['eh'].value, args)
410
411        if options['debugstl'].value:
412            args.append('-D_GLIBCXX_DEBUG=1')
413        return args
414
415
416class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler):
417    def __init__(self, exelist, version, for_machine: MachineChoice,
418                 is_cross, info: 'MachineInfo', exe_wrap, **kwargs):
419        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
420                             info, exe_wrap, **kwargs)
421        IntelGnuLikeCompiler.__init__(self)
422        self.lang_header = 'c++-header'
423        default_warn_args = ['-Wall', '-w3', '-diag-disable:remark',
424                             '-Wpch-messages', '-Wnon-virtual-dtor']
425        self.warn_args = {'0': [],
426                          '1': default_warn_args,
427                          '2': default_warn_args + ['-Wextra'],
428                          '3': default_warn_args + ['-Wextra']}
429
430    def get_options(self):
431        opts = CPPCompiler.get_options(self)
432        # Every Unix compiler under the sun seems to accept -std=c++03,
433        # with the exception of ICC. Instead of preventing the user from
434        # globally requesting C++03, we transparently remap it to C++98
435        c_stds = ['c++98', 'c++03']
436        g_stds = ['gnu++98', 'gnu++03']
437        if version_compare(self.version, '>=15.0.0'):
438            c_stds += ['c++11', 'c++14']
439            g_stds += ['gnu++11']
440        if version_compare(self.version, '>=16.0.0'):
441            c_stds += ['c++17']
442        if version_compare(self.version, '>=17.0.0'):
443            g_stds += ['gnu++14']
444        opts.update({
445            'eh': coredata.UserComboOption(
446                'C++ exception handling type.',
447                ['none', 'default', 'a', 's', 'sc'],
448                'default',
449            ),
450            'rtti': coredata.UserBooleanOption('Enable RTTI', True),
451            'std': coredata.UserComboOption(
452                'C++ language standard to use',
453                ['none'] + c_stds + g_stds,
454                'none',
455            ),
456            'debugstl': coredata.UserBooleanOption('STL debug mode', False),
457        })
458        return opts
459
460    def get_option_compile_args(self, options):
461        args = []
462        std = options['std']
463        if std.value != 'none':
464            remap_cpp03 = {
465                'c++03': 'c++98',
466                'gnu++03': 'gnu++98'
467            }
468            args.append('-std=' + remap_cpp03.get(std.value, std.value))
469        if options['eh'].value == 'none':
470            args.append('-fno-exceptions')
471        if not options['rtti'].value:
472            args.append('-fno-rtti')
473        if options['debugstl'].value:
474            args.append('-D_GLIBCXX_DEBUG=1')
475        return args
476
477    def get_option_link_args(self, options):
478        return []
479
480
481class VisualStudioLikeCPPCompilerMixin:
482
483    """Mixin for C++ specific method overrides in MSVC-like compilers."""
484
485    VC_VERSION_MAP = {
486        'none': (True, None),
487        'vc++11': (True, 11),
488        'vc++14': (True, 14),
489        'vc++17': (True, 17),
490        'vc++latest': (True, "latest"),
491        'c++11': (False, 11),
492        'c++14': (False, 14),
493        'c++17': (False, 17),
494        'c++latest': (False, "latest"),
495    }
496
497    def get_option_link_args(self, options):
498        return options['winlibs'].value[:]
499
500    def _get_options_impl(self, opts, cpp_stds: T.List[str]):
501        opts.update({
502            'eh': coredata.UserComboOption(
503                'C++ exception handling type.',
504                ['none', 'default', 'a', 's', 'sc'],
505                'default',
506            ),
507            'rtti': coredata.UserBooleanOption('Enable RTTI', True),
508            'std': coredata.UserComboOption(
509                'C++ language standard to use',
510                cpp_stds,
511                'none',
512            ),
513            'winlibs': coredata.UserArrayOption(
514                'Windows libs to link against.',
515                msvc_winlibs,
516            ),
517        })
518        return opts
519
520    def get_option_compile_args(self, options):
521        args = []
522
523        eh = options['eh']
524        if eh.value == 'default':
525            args.append('/EHsc')
526        elif eh.value == 'none':
527            args.append('/EHs-c-')
528        else:
529            args.append('/EH' + eh.value)
530
531        if not options['rtti'].value:
532            args.append('/GR-')
533
534        permissive, ver = self.VC_VERSION_MAP[options['std'].value]
535
536        if ver is not None:
537            args.append('/std:c++{}'.format(ver))
538
539        if not permissive:
540            args.append('/permissive-')
541
542        return args
543
544    def get_compiler_check_args(self):
545        # XXX: this is a hack because so much GnuLike stuff is in the base CPPCompiler class.
546        return CLikeCompiler.get_compiler_check_args(self)
547
548
549class CPP11AsCPP14Mixin:
550
551    """Mixin class for VisualStudio and ClangCl to replace C++11 std with C++14.
552
553    This is a limitation of Clang and MSVC that ICL doesn't share.
554    """
555
556    def get_option_compile_args(self, options):
557        # Note: there is no explicit flag for supporting C++11; we attempt to do the best we can
558        # which means setting the C++ standard version to C++14, in compilers that support it
559        # (i.e., after VS2015U3)
560        # if one is using anything before that point, one cannot set the standard.
561        if options['std'].value in {'vc++11', 'c++11'}:
562            mlog.warning(self.id, 'does not support C++11;',
563                         'attempting best effort; setting the standard to C++14', once=True)
564            # Don't mutate anything we're going to change, we need to use
565            # deepcopy since we're messing with members, and we can't simply
566            # copy the members because the option proxy doesn't support it.
567            options = copy.deepcopy(options)
568            if options['std'].value == 'vc++11':
569                options['std'].value = 'vc++14'
570            else:
571                options['std'].value = 'c++14'
572        return super().get_option_compile_args(options)
573
574
575class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, MSVCCompiler, CPPCompiler):
576    def __init__(self, exelist, version, for_machine: MachineChoice,
577                 is_cross: bool, info: 'MachineInfo', exe_wrap, target, **kwargs):
578        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, info, exe_wrap, **kwargs)
579        MSVCCompiler.__init__(self, target)
580        self.base_options = ['b_pch', 'b_vscrt'] # FIXME add lto, pgo and the like
581        self.id = 'msvc'
582
583    def get_options(self):
584        cpp_stds = ['none', 'c++11', 'vc++11']
585        # Visual Studio 2015 and later
586        if version_compare(self.version, '>=19'):
587            cpp_stds.extend(['c++14', 'c++latest', 'vc++latest'])
588        # Visual Studio 2017 and later
589        if version_compare(self.version, '>=19.11'):
590            cpp_stds.extend(['vc++14', 'c++17', 'vc++17'])
591        return self._get_options_impl(super().get_options(), cpp_stds)
592
593    def get_option_compile_args(self, options):
594        if options['std'].value != 'none' and version_compare(self.version, '<19.00.24210'):
595            mlog.warning('This version of MSVC does not support cpp_std arguments')
596            options = copy.copy(options)
597            options['std'].value = 'none'
598
599        args = super().get_option_compile_args(options)
600
601        if version_compare(self.version, '<19.11'):
602            try:
603                i = args.index('/permissive-')
604            except ValueError:
605                return args
606            del args[i]
607        return args
608
609class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, ClangClCompiler, CPPCompiler):
610    def __init__(self, exelist, version, for_machine: MachineChoice,
611                 is_cross, info: 'MachineInfo', exe_wrap, target, **kwargs):
612        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
613                             info, exe_wrap, **kwargs)
614        ClangClCompiler.__init__(self, target)
615        self.id = 'clang-cl'
616
617    def get_options(self):
618        cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest']
619        return self._get_options_impl(super().get_options(), cpp_stds)
620
621
622class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLikeCompiler, CPPCompiler):
623
624    def __init__(self, exelist, version, for_machine: MachineChoice,
625                 is_cross, info: 'MachineInfo', exe_wrap, target, **kwargs):
626        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
627                             info, exe_wrap, **kwargs)
628        IntelVisualStudioLikeCompiler.__init__(self, target)
629
630    def get_options(self):
631        # This has only been tested with version 19.0,
632        cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest']
633        return self._get_options_impl(super().get_options(), cpp_stds)
634
635
636class ArmCPPCompiler(ArmCompiler, CPPCompiler):
637    def __init__(self, exelist, version, for_machine: MachineChoice,
638                 is_cross, info: 'MachineInfo', exe_wrap=None, **kwargs):
639        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
640                             info, exe_wrap, **kwargs)
641        ArmCompiler.__init__(self)
642
643    def get_options(self):
644        opts = CPPCompiler.get_options(self)
645        opts.update({
646            'std': coredata.UserComboOption(
647                'C++ language standard to use',
648                ['none', 'c++03', 'c++11'],
649                'none',
650            ),
651        })
652        return opts
653
654    def get_option_compile_args(self, options):
655        args = []
656        std = options['std']
657        if std.value == 'c++11':
658            args.append('--cpp11')
659        elif std.value == 'c++03':
660            args.append('--cpp')
661        return args
662
663    def get_option_link_args(self, options):
664        return []
665
666    def get_compiler_check_args(self):
667        return []
668
669
670class CcrxCPPCompiler(CcrxCompiler, CPPCompiler):
671    def __init__(self, exelist, version, for_machine: MachineChoice,
672                 is_cross, info: 'MachineInfo', exe_wrap=None, **kwargs):
673        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
674                             info, exe_wrap, **kwargs)
675        CcrxCompiler.__init__(self)
676
677    # Override CCompiler.get_always_args
678    def get_always_args(self):
679        return ['-nologo', '-lang=cpp']
680
681    def get_option_compile_args(self, options):
682        return []
683
684    def get_compile_only_args(self):
685        return []
686
687    def get_output_args(self, target):
688        return ['-output=obj=%s' % target]
689
690    def get_option_link_args(self, options):
691        return []
692
693    def get_compiler_check_args(self):
694        return []
695
696class C2000CPPCompiler(C2000Compiler, CPPCompiler):
697    def __init__(self, exelist, version, for_machine: MachineChoice,
698                 is_cross, info: 'MachineInfo', exe_wrap=None, **kwargs):
699        CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
700                             info, exe_wrap, **kwargs)
701        C2000Compiler.__init__(self)
702
703    def get_options(self):
704        opts = CPPCompiler.get_options(self)
705        opts.update({'cpp_std': coredata.UserComboOption('C++ language standard to use',
706                                                         ['none', 'c++03'],
707                                                         'none')})
708        return opts
709
710    def get_always_args(self):
711        return ['-nologo', '-lang=cpp']
712
713    def get_option_compile_args(self, options):
714        return []
715
716    def get_compile_only_args(self):
717        return []
718
719    def get_output_args(self, target):
720        return ['-output=obj=%s' % target]
721
722    def get_option_link_args(self, options):
723        return []
724
725    def get_compiler_check_args(self):
726        return []
727