@@ -6,6 +6,231 @@ import cpp
66abstract class CompilerExtension extends Locatable { }
77
88/**
9- * Common base class for modeling compiler extensions in CPP.
9+ * A usage of a compiler extension in C++ code, such as non-standard attributes or built-in function
10+ * calls.
1011 */
11- abstract class CPPCompilerExtension extends CompilerExtension { }
12+ abstract class CPPCompilerExtension extends CompilerExtension {
13+ abstract string getMessage ( ) ;
14+ }
15+
16+ /**
17+ * An `Attribute` that may be a `GnuAttribute` or `Declspec`, or `MicrosoftAttribute`, etc.
18+ *
19+ * There are language extensions such as GNU `__attribute__`, Microsoft `__declspec` or
20+ * `[attribute]` syntax.
21+ */
22+ class CPPAttributeExtension extends CPPCompilerExtension , Attribute {
23+ CPPAttributeExtension ( ) { not this instanceof StdAttribute and not this instanceof AlignAs }
24+
25+ override string getMessage ( ) {
26+ result =
27+ "Use of attribute '" + getName ( ) +
28+ "' is a compiler extension and is not portable to other compilers."
29+ }
30+ }
31+
32+ /**
33+ * A `StdAttribute` within a compiler specific namespace such as `[[gnu::weak]]`.
34+ */
35+ class CPPNamespacedStdAttributeExtension extends CPPCompilerExtension , StdAttribute {
36+ CPPNamespacedStdAttributeExtension ( ) { exists ( this .getNamespace ( ) ) and not getNamespace ( ) = "" }
37+
38+ override string getMessage ( ) {
39+ result =
40+ "Use of attribute '" + getName ( ) + "' in namespace '" + getNamespace ( ) +
41+ "' is a compiler extension and is not portable to other compilers."
42+ }
43+ }
44+
45+ /**
46+ * A `StdAttribute` with a name not recognized as part of the C++17 standard.
47+ *
48+ * Only the listed names are valid C++17. Namespaced attributes are handled by
49+ * `CPPNamespacedStdAttributeExtension` and not considered here.
50+ */
51+ class CPPUnrecognizedAttributeExtension extends CPPCompilerExtension , StdAttribute {
52+ CPPUnrecognizedAttributeExtension ( ) {
53+ not this instanceof CPPNamespacedStdAttributeExtension and
54+ not getName ( ) in [
55+ "maybe_unused" , "nodiscard" , "noreturn" , "deprecated" , "carries_dependency" , "fallthrough"
56+ ]
57+ }
58+
59+ override string getMessage ( ) {
60+ result = "Use of unrecognized or non-C++17 attribute '" + getName ( ) + "'."
61+ }
62+ }
63+
64+ /**
65+ * A `FunctionCall` of a compiler-specific builtin function.
66+ *
67+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
68+ */
69+ class CPPBuiltinFunctionExtension extends CPPCompilerExtension , FunctionCall {
70+ CPPBuiltinFunctionExtension ( ) {
71+ getTarget ( ) .getName ( ) .indexOf ( "__builtin_" ) = 0 or
72+ getTarget ( ) .getName ( ) .indexOf ( "__sync_" ) = 0 or
73+ getTarget ( ) .getName ( ) .indexOf ( "__atomic_" ) = 0
74+ }
75+
76+ override string getMessage ( ) {
77+ result =
78+ "Call to builtin function '" + getTarget ( ) .getName ( ) +
79+ "' is a compiler extension and is not portable to other compilers."
80+ }
81+ }
82+
83+ /**
84+ * A `StmtExpr`, which uses `({ <stmts> })` syntax, which is a GNU extension.
85+ *
86+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
87+ */
88+ class CPPStmtExprExtension extends CPPCompilerExtension , StmtExpr {
89+ override string getMessage ( ) {
90+ result =
91+ "Statement expressions are a compiler extension and are not portable to other compilers."
92+ }
93+ }
94+
95+ /**
96+ * A `ConditionalExpr` using GNU-style omitted middle operand such as `x ?: y`.
97+ *
98+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/Conditionals.html
99+ */
100+ class CPPTerseTernaryExtension extends CPPCompilerExtension , ConditionalExpr {
101+ CPPTerseTernaryExtension ( ) { getCondition ( ) = getElse ( ) or getCondition ( ) = getThen ( ) }
102+
103+ override string getMessage ( ) {
104+ result =
105+ "Ternaries with omitted middle operands are a compiler extension and are not portable to " +
106+ "other compilers."
107+ }
108+ }
109+
110+ /**
111+ * A non-standard `Type` that is only available as a compiler extension, such as `__int128`,
112+ * `_Decimal32`, `_Decimal64`, `_Decimal128`, or `__float128`.
113+ *
114+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/__int128.html
115+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/Decimal-Float.html
116+ */
117+ class CPPExtensionType extends Type {
118+ CPPExtensionType ( ) {
119+ this instanceof Int128Type or
120+ this instanceof Decimal128Type or
121+ this instanceof Decimal32Type or
122+ this instanceof Decimal64Type or
123+ this instanceof Float128Type
124+ }
125+ }
126+
127+ /**
128+ * A `DeclarationEntry` using an extended type such as `__int128`, `_Decimal32`, `_Decimal64`,
129+ * `_Decimal128`, or `__float128`.
130+ *
131+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/__int128.html
132+ */
133+ class CPPExtensionTypeUsage extends CPPCompilerExtension , DeclarationEntry {
134+ CPPExtensionType extendedType ;
135+
136+ CPPExtensionTypeUsage ( ) { extendedType = getType ( ) }
137+
138+ override string getMessage ( ) {
139+ result =
140+ "Declaration of variable '" + getName ( ) + "' as type '" + extendedType .getName ( ) +
141+ "' requires a compiler extension and is not portable to other compilers."
142+ }
143+ }
144+
145+ /**
146+ * A `DeclarationEntry` using a zero-length array, which is a non-standard way to declare a flexible
147+ * array member.
148+ *
149+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
150+ */
151+ class CPPZeroLengthArraysExtension extends CPPCompilerExtension , DeclarationEntry {
152+ ArrayType array ;
153+
154+ CPPZeroLengthArraysExtension ( ) {
155+ array = getType ( ) and
156+ array .getArraySize ( ) = 0
157+ }
158+
159+ override string getMessage ( ) {
160+ result =
161+ "Declaration of variable '" + getName ( ) + "' as a zero-length array (of '" +
162+ array .getBaseType ( ) +
163+ "') requires a compiler extension and is not portable to other compilers."
164+ }
165+ }
166+
167+ /**
168+ * A `Field` with a variable-length array type in a struct member (not C++17 compliant).
169+ *
170+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html
171+ */
172+ class CPPVariableLengthArraysExtension extends CPPCompilerExtension , VlaDeclStmt {
173+ override string getMessage ( ) {
174+ result =
175+ "Variable length array (used in '" + this +
176+ "') are a compiler extension and are not portable to other compilers."
177+ }
178+ }
179+
180+ /**
181+ * A `PreprocessorIfdef` using a builtin preprocessor feature such as `__has_builtin`,
182+ * `__has_include`, etc., which are non-standard clang extensions.
183+ *
184+ * Reference: https://clang.llvm.org/docs/LanguageExtensions.html
185+ */
186+ class CPPConditionalDefineExtension extends CPPCompilerExtension , PreprocessorIfdef {
187+ string feature ;
188+
189+ CPPConditionalDefineExtension ( ) {
190+ feature =
191+ [
192+ "__has_builtin" , "__has_constexpr_builtin" , "__has_feature" , "__has_extension" ,
193+ "__has_attribute" , "__has_declspec_attribute" , "__is_identifier" , "__has_include" ,
194+ "__has_include_next" , "__has_warning" , "__has_cpp_attribute"
195+ ] and
196+ exists ( toString ( ) .indexOf ( feature ) )
197+ }
198+
199+ override string getMessage ( ) {
200+ result =
201+ "Call to builtin preprocessor feature '" + feature +
202+ "' is a compiler extension and is not portable to other compilers."
203+ }
204+ }
205+
206+ /**
207+ * A `PreprocessorDirective` that is a non-standard compiler extension, such as `#pragma`, `#error`,
208+ * or `#warning`.
209+ */
210+ class CPPPreprocessorDirectiveExtension extends CPPCompilerExtension , PreprocessorDirective {
211+ string kind ;
212+
213+ CPPPreprocessorDirectiveExtension ( ) {
214+ this instanceof PreprocessorPragma and kind = "#pragma " + getHead ( )
215+ or
216+ this instanceof PreprocessorError and kind = "#error"
217+ or
218+ this instanceof PreprocessorWarning and kind = "#warning"
219+ }
220+
221+ override string getMessage ( ) {
222+ result = "Use of non-standard preprocessor directive '" + kind + "' is a compiler extension."
223+ }
224+ }
225+
226+ /**
227+ * A `BuiltInOperation` which describes certain non-standard syntax such as type trait operations,
228+ * for example GNU `__is_abstract(T)`, `__is_same(T, U)`, etc.
229+ *
230+ * Reference: https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
231+ */
232+ class CPPBuiltinOperationExtension extends CPPCompilerExtension , BuiltInOperation {
233+ override string getMessage ( ) {
234+ result = "Use of built-in operation '" + toString ( ) + "' is a compiler extension."
235+ }
236+ }
0 commit comments