diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/FixIt/fixit-pragma-attribute.c | 6 | ||||
-rw-r--r-- | clang/test/FixIt/fixit-pragma-attribute.cpp | 83 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp | 169 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-cxx.cpp | 106 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-objc-subject-match-rules.m | 113 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-objc.m | 164 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-strict-subjects.c | 222 | ||||
-rw-r--r-- | clang/test/Misc/pragma-attribute-supported-attributes-list.test | 62 | ||||
-rw-r--r-- | clang/test/Parser/pragma-attribute-declspec.cpp | 13 | ||||
-rw-r--r-- | clang/test/Parser/pragma-attribute.cpp | 181 | ||||
-rw-r--r-- | clang/test/Sema/pragma-attribute-strict-subjects.c | 153 | ||||
-rw-r--r-- | clang/test/Sema/pragma-attribute.c | 47 | ||||
-rw-r--r-- | clang/test/lit.cfg | 2 | ||||
-rw-r--r-- | clang/test/lit.site.cfg.in | 1 |
14 files changed, 1322 insertions, 0 deletions
diff --git a/clang/test/FixIt/fixit-pragma-attribute.c b/clang/test/FixIt/fixit-pragma-attribute.c new file mode 100644 index 00000000000..f166eb2978e --- /dev/null +++ b/clang/test/FixIt/fixit-pragma-attribute.c @@ -0,0 +1,6 @@ +// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// Verify that the suggested attribute subject match rules don't include the +// rules that are not applicable in the current language mode. + +#pragma clang attribute push (__attribute__((abi_tag("a")))) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", apply_to = any(record(unless(is_union)), variable, function)" diff --git a/clang/test/FixIt/fixit-pragma-attribute.cpp b/clang/test/FixIt/fixit-pragma-attribute.cpp new file mode 100644 index 00000000000..8e3f6d9392f --- /dev/null +++ b/clang/test/FixIt/fixit-pragma-attribute.cpp @@ -0,0 +1,83 @@ +// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wno-pragma-clang-attribute %s 2>&1 | FileCheck %s + +#pragma clang attribute push (annotate) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:31-[[@LINE-1]]:31}:"__attribute__((" +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:39-[[@LINE-2]]:39}:"))" +#pragma clang attribute push (annotate(("test"))) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:31-[[@LINE-1]]:31}:"__attribute__((" +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:49-[[@LINE-2]]:49}:"))" + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( enum, function, function, namespace, function )) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:97-[[@LINE-1]]:107}:"" +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:118-[[@LINE-2]]:127}:"" + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_global), function, variable(is_global), variable(is_global) )) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:112-[[@LINE-1]]:133}:"" +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:133-[[@LINE-2]]:153}:"" + +#pragma clang attribute push (__attribute__((annotate("subRuleContradictions"))), apply_to = any(variable, variable(is_parameter), function(is_member), variable(is_global))) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:108-[[@LINE-1]]:132}:"" +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:153-[[@LINE-2]]:172}:"" + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("subRuleContradictions2"))), apply_to = any(function(is_member),function)) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:99-[[@LINE-1]]:119}:"" + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions1"))), apply_to = any(variable(is_parameter), variable(unless(is_parameter)))) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:130-[[@LINE-1]]:160}:"" +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions2"))), apply_to = any(variable(unless(is_parameter)), variable(is_thread_local), function, variable(is_global))) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:106-[[@LINE-1]]:137}:"" +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(enum, variable)) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:77-[[@LINE-1]]:82}:"" +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a")))) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", apply_to = any(record(unless(is_union)), variable, function, namespace)" +#pragma clang attribute push (__attribute__((abi_tag("a"))) apply_to=function) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", " +#pragma clang attribute push (__attribute__((abi_tag("a"))) = function) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", apply_to" +#pragma clang attribute push (__attribute__((abi_tag("a"))) any(function)) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:60}:", apply_to = " + +#pragma clang attribute push (__attribute__((abi_tag("a"))) 22) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:63}:", apply_to = any(record(unless(is_union)), variable, function, namespace)" +#pragma clang attribute push (__attribute__((abi_tag("a"))) function) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:69}:", apply_to = any(record(unless(is_union)), variable, function, namespace)" +#pragma clang attribute push (__attribute__((abi_tag("a"))) (function)) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:60-[[@LINE-1]]:71}:", apply_to = any(record(unless(is_union)), variable, function, namespace)" + +#pragma clang attribute push (__attribute__((abi_tag("a"))), ) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:62}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" +#pragma clang attribute push (__attribute__((abi_tag("a"))), = function) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:61}:"apply_to" +#pragma clang attribute push (__attribute__((abi_tag("a"))), any(function)) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:61}:"apply_to = " + +#pragma clang attribute push (__attribute__((abi_tag("a"))), 22) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:64}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" +#pragma clang attribute push (__attribute__((abi_tag("a"))), 1, 2) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:66}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" +#pragma clang attribute push (__attribute__((abi_tag("a"))), function) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:70}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" +#pragma clang attribute push (__attribute__((abi_tag("a"))), (function)) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:61-[[@LINE-1]]:72}:"apply_to = any(record(unless(is_union)), variable, function, namespace)" + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:70-[[@LINE-1]]:70}:" = any(record(unless(is_union)), variable, function, namespace)" +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to any(function)) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:70-[[@LINE-1]]:70}:" = " + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to 41 (22)) +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:70-[[@LINE-1]]:78}:" = any(record(unless(is_union)), variable, function, namespace)" + +// Don't give fix-it to attributes without a strict subject set +#pragma clang attribute push (__attribute__((annotate("a")))) +// CHECK-NO: [[@LINE-1]]:61 diff --git a/clang/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp b/clang/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp new file mode 100644 index 00000000000..b7741343ad4 --- /dev/null +++ b/clang/test/Misc/pragma-attribute-cxx-subject-match-rules.cpp @@ -0,0 +1,169 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=namespace" %s | FileCheck --check-prefix=CHECK-NAMESPACE %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=type_alias" %s | FileCheck --check-prefix=CHECK-TYPE_ALIAS %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=enum" %s | FileCheck --check-prefix=CHECK-ENUM %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=enum_constant" %s | FileCheck --check-prefix=CHECK-ENUM_CONSTANT %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=record" %s | FileCheck --check-prefix=CHECK-RECORD %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=record(unless(is_union))" %s | FileCheck --check-prefix=CHECK-RECORD_UNLESS_IS_UNION %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=field" %s | FileCheck --check-prefix=CHECK-FIELD %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=function" %s | FileCheck --check-prefix=CHECK-FUNCTION %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=hasType(functionType)" %s | FileCheck --check-prefix=CHECK-HAS_TYPE_FUNCTION_TYPE %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=function(is_member)" %s | FileCheck --check-prefix=CHECK-FUNCTION_IS_MEMBER %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=variable" %s | FileCheck --check-prefix=CHECK-VARIABLE %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=variable(is_global)" %s | FileCheck --check-prefix=CHECK-VARIABLE_IS_GLOBAL %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=variable(is_parameter)" %s | FileCheck --check-prefix=CHECK-VARIABLE_IS_PARAMETER %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=variable(unless(is_parameter))" %s | FileCheck --check-prefix=CHECK-VARIABLE_UNLESS_IS_PARAMETER %s + +#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(SUBJECT)) + +namespace testNamespace { +// CHECK-NAMESPACE: NamespaceDecl{{.*}} testNamespace +// CHECK-NAMESPACE-NEXT: AnnotateAttr{{.*}} "test" + +typedef int testTypedef; +// CHECK-TYPE_ALIAS: TypedefDecl{{.*}} testTypedef +// CHECK-TYPE_ALIAS-NEXT: BuiltinType +// CHECK-TYPE_ALIAS-NEXT: AnnotateAttr{{.*}} "test" + +using testTypeAlias = double; +// CHECK-TYPE_ALIAS: TypeAliasDecl{{.*}} testTypeAlias +// CHECK-TYPE_ALIAS-NEXT: BuiltinType +// CHECK-TYPE_ALIAS-NEXT: AnnotateAttr{{.*}} "test" + +enum testEnum { + testEnumCase1, + testEnumCase2 +}; +// CHECK-ENUM: EnumDecl{{.*}} testEnum +// CHECK-ENUM-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-ENUM_CONSTANT: EnumConstantDecl{{.*}} testEnumCase1 +// CHECK-ENUM_CONSTANT-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-ENUM_CONSTANT: EnumConstantDecl{{.*}} testEnumCase2 +// CHECK-ENUM_CONSTANT-NEXT: AnnotateAttr{{.*}} "test" + +struct testStructRecord { + int testStructRecordField; +}; +// CHECK-RECORD: CXXRecordDecl{{.*}} testStructRecord +// CHECK-RECORD-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-RECORD_UNLESS_IS_UNION-LABEL: CXXRecordDecl{{.*}} testStructRecord +// CHECK-RECORD_UNLESS_IS_UNION-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-FIELD: FieldDecl{{.*}} testStructRecordField +// CHECK-FIELD-NEXT: AnnotateAttr{{.*}} "test" + +class testClassRecord { + int testClassRecordField; +}; +// CHECK-RECORD: CXXRecordDecl{{.*}} testClassRecord +// CHECK-RECORD-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-RECORD_UNLESS_IS_UNION-LABEL: CXXRecordDecl{{.*}} testClassRecord +// CHECK-RECORD_UNLESS_IS_UNION-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-FIELD: FieldDecl{{.*}} testClassRecordField +// CHECK-FIELD-NEXT: AnnotateAttr{{.*}} "test" + +union testUnionRecord { + int testUnionRecordField; +}; +// CHECK-RECORD: CXXRecordDecl{{.*}} testUnionRecord +// CHECK-RECORD-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-RECORD_UNLESS_IS_UNION-LABEL: CXXRecordDecl{{.*}} testUnionRecord +// CHECK-RECORD_UNLESS_IS_UNION-NOT: AnnotateAttr{{.*}} "test" +// CHECK-FIELD: FieldDecl{{.*}} testUnionRecordField +// CHECK-FIELD-NEXT: AnnotateAttr{{.*}} "test" + +// CHECK-RECORD_UNLESS_IS_UNION-LABEL: CXXRecordDecl +void testFunctionDecl(); +// CHECK-FUNCTION: FunctionDecl{{.*}} testFunctionDecl +// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE: FunctionDecl{{.*}} testFunctionDecl +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" + +void testFunctionDecl() { } +// CHECK-FUNCTION: FunctionDecl{{.*}} testFunctionDecl +// CHECK-FUNCTION-NEXT: CompoundStmt +// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE: FunctionDecl{{.*}} testFunctionDecl +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: CompoundStmt +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" + +void (*testFunctionVar)(); +// CHECK-HAS_TYPE_FUNCTION_TYPE: VarDecl{{.*}} testFunctionVar +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" +// 'function' should not apply to variables with a function type! +// CHECK-FUNCTION: VarDecl{{.*}} testFunctionVar +// CHECK-FUNCTION-NOT: AnnotateAttr{{.*}} "test" + +class testMethods { + testMethods(); + void testMethod(); +}; +void testMethods::testMethod() { } +void testFunctionNotMethod(); +// CHECK-FUNCTION-LABEL: CXXConstructorDecl{{.*}} testMethods +// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-FUNCTION_IS_MEMBER: CXXConstructorDecl{{.*}} testMethods +// CHECK-FUNCTION_IS_MEMBER-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE: CXXConstructorDecl{{.*}} testMethods +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-FUNCTION: CXXMethodDecl{{.*}} testMethod +// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-FUNCTION_IS_MEMBER: CXXMethodDecl{{.*}} testMethod +// CHECK-FUNCTION_IS_MEMBER-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE: CXXMethodDecl{{.*}} testMethod +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-FUNCTION: CXXMethodDecl{{.*}} testMethod +// CHECK-FUNCTION-NEXT: CompoundStmt +// CHECK-FUNCTION-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-FUNCTION_IS_MEMBER: CXXMethodDecl{{.*}} testMethod +// CHECK-FUNCTION_IS_MEMBER-NEXT: CompoundStmt +// CHECK-CXX_METHOD-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE: CXXMethodDecl{{.*}} testMethod +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: CompoundStmt +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-FUNCTION_IS_MEMBER: FunctionDecl{{.*}} testFunctionNotMethod +// CHECK-FUNCTION_IS_MEMBER-NOT: AnnotateAttr{{.*}} "test" + +int testVariable; +// CHECK-VARIABLE: VarDecl{{.*}} testVariable +// CHECK-VARIABLE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_IS_GLOBAL-LABEL: VarDecl{{.*}} testVariable +// CHECK-VARIABLE_IS_GLOBAL-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_IS_PARAMETER-LABEL: VarDecl{{.*}} testVariable +// CHECK-VARIABLE_IS_PARAMETER-NOT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_UNLESS_IS_PARAMETER-LABEL: VarDecl{{.*}} testVariable +// CHECK-VARIABLE_UNLESS_IS_PARAMETER-NEXT: AnnotateAttr{{.*}} "test" +void testVarFunction(int testParam) { +// CHECK-VARIABLE: VarDecl{{.*}} testParam +// CHECK-VARIABLE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_IS_GLOBAL-LABEL: VarDecl{{.*}} testParam +// CHECK-VARIABLE_IS_GLOBAL-NOT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_IS_PARAMETER-LABEL: VarDecl{{.*}} testParam +// CHECK-VARIABLE_IS_PARAMETER-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_UNLESS_IS_PARAMETER-LABEL: VarDecl{{.*}} testParam +// CHECK-VARIABLE_UNLESS_IS_PARAMETER-NOT: AnnotateAttr{{.*}} "test" + + int testLocalVariable; +// CHECK-VARIABLE: VarDecl{{.*}} testLocalVariable +// CHECK-VARIABLE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_IS_GLOBAL-LABEL: VarDecl{{.*}} testLocalVariable +// CHECK-VARIABLE_IS_GLOBAL-NOT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_IS_PARAMETER-LABEL: VarDecl{{.*}} testLocalVariable +// CHECK-VARIABLE_IS_PARAMETER-NOT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_UNLESS_IS_PARAMETER-LABEL: VarDecl{{.*}} testLocalVariable +// CHECK-VARIABLE_UNLESS_IS_PARAMETER-NEXT: AnnotateAttr{{.*}} "test" +} +class testVarClass { + static int testStaticVar; +}; +// CHECK-VARIABLE: VarDecl{{.*}} testStaticVar +// CHECK-VARIABLE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_IS_GLOBAL-LABEL: VarDecl{{.*}} testStaticVar +// CHECK-VARIABLE_IS_GLOBAL-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_IS_PARAMETER-LABEL: VarDecl{{.*}} testStaticVar +// CHECK-VARIABLE_IS_PARAMETER-NOT: AnnotateAttr{{.*}} "test" +// CHECK-VARIABLE_UNLESS_IS_PARAMETER-LABEL: VarDecl{{.*}} testStaticVar +// CHECK-VARIABLE_UNLESS_IS_PARAMETER-NEXT: AnnotateAttr{{.*}} "test" + + +} + +#pragma clang attribute pop diff --git a/clang/test/Misc/pragma-attribute-cxx.cpp b/clang/test/Misc/pragma-attribute-cxx.cpp new file mode 100644 index 00000000000..c241c4e4bdb --- /dev/null +++ b/clang/test/Misc/pragma-attribute-cxx.cpp @@ -0,0 +1,106 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s +// RUN: %clang_cc1 -fsyntax-only -ast-dump -ast-dump-filter test -std=c++11 -fcxx-exceptions %s | FileCheck %s +// expected-no-diagnostics + +class testClass1 { +}; +// CHECK-LABEL: CXXRecordDecl{{.*}} testClass1 +// CHECK-NOT: AnnotateAttr + +#pragma clang attribute push (__attribute__((annotate("test"))), apply_to=any(record, field, variable, function, namespace, type_alias)) + +class testClass2 { + void testMethod1(int param); + + testClass2(); + + testClass2 *operator -> (); +}; +// CHECK-LABEL: CXXRecordDecl{{.*}} testClass2 +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK: CXXMethodDecl{{.*}} testMethod1 +// CHECK-NEXT: ParmVarDecl{{.*}} param +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: CXXConstructorDecl +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: CXXMethodDecl{{.*}} operator-> +// CHECK-NEXT: AnnotateAttr{{.*}} "test" + +#pragma clang attribute push (__attribute__((annotate("method"))), apply_to=any(record, field, variable, function, namespace, type_alias)) + +void testClass2::testMethod1(int param) { + +#pragma clang attribute pop +} +// CHECK-LABEL: CXXMethodDecl{{.*}}prev{{.*}} testMethod1 +// CHECK-NEXT: ParmVarDecl{{.*}} param +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: AnnotateAttr{{.*}} "method" +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: AnnotateAttr{{.*}} "method" + +namespace testNamespace { +} +// CHECK-LABEL: NamespaceDecl{{.*}} testNamespace +// CHECK-NEXT: AnnotateAttr{{.*}} "test" + +class testClassForward; +// CHECK-LABEL: CXXRecordDecl{{.*}} testClassForward +// CHECK-NEXT: AnnotateAttr{{.*}} "test" + +namespace testNamespaceAlias = testNamespace; +// CHECK-LABEL: NamespaceAliasDecl{{.*}} testNamespaceAlias +// CHECK-NOT: AnnotateAttr + +using testTypeAlias = testClass2; +// CHECK-LABEL: TypeAliasDecl{{.*}} testTypeAlias +// CHECK: AnnotateAttr{{.*}} "test" + +void testCatchVariable() { + try { + } catch (int testCatch) { + } + testCatchVariable(); +} +// CHECK-LABEL: FunctionDecl{{.*}} testCatchVariable +// CHECK: CXXCatchStmt +// CHECK-NEXT: VarDecl{{.*}} testCatch +// CHECK-NEXT: AnnotateAttr{{.*}} "test" + +void testLambdaMethod() { + auto l = [] () { }; + testLambdaMethod(); +} +// CHECK-LABEL: FunctionDecl{{.*}} testLambdaMethod +// CHECK: LambdaExpr +// CHECK-NEXT: CXXRecordDecl +// CHECK-NEXT: CXXMethodDecl{{.*}} operator() +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: AnnotateAttr{{.*}} "test" + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((require_constant_initialization)), apply_to=variable(is_global)) + +int testCI1 = 1; +// CHECK-LABEL: VarDecl{{.*}} testCI1 +// CHECK-NEXT: IntegerLiteral +// CHECK-NEXT: RequireConstantInitAttr + +#pragma clang attribute pop + +int testNoCI = 0; +// CHECK-LABEL: VarDecl{{.*}} testNoCI +// CHECK-NEXT: IntegerLiteral +// CHECK-NOT: RequireConstantInitAttr + +// Check support for CXX11 style attributes +#pragma clang attribute push ([[noreturn]], apply_to = function) + +void testNoReturn(); +// CHECK-LABEL: FunctionDecl{{.*}} testNoReturn +// CHECK-NEXT: CXX11NoReturnAttr + +#pragma clang attribute pop diff --git a/clang/test/Misc/pragma-attribute-objc-subject-match-rules.m b/clang/test/Misc/pragma-attribute-objc-subject-match-rules.m new file mode 100644 index 00000000000..09ab5e1f33a --- /dev/null +++ b/clang/test/Misc/pragma-attribute-objc-subject-match-rules.m @@ -0,0 +1,113 @@ +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump "-DSUBJECT=objc_interface" %s | FileCheck --check-prefix=CHECK-OBJC_INTERFACE %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=objc_protocol" %s | FileCheck --check-prefix=CHECK-OBJC_PROTOCOL %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump "-DSUBJECT=objc_category" %s | FileCheck --check-prefix=CHECK-OBJC_CATEGORY %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=objc_method" %s | FileCheck --check-prefix=CHECK-OBJC_METHOD %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=objc_method(is_instance)" %s | FileCheck --check-prefix=CHECK-OBJC_METHOD_IS_INSTANCE %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=field" %s | FileCheck --check-prefix=CHECK-FIELD %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=objc_property" %s | FileCheck --check-prefix=CHECK-OBJC_PROPERTY %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=block" %s | FileCheck --check-prefix=CHECK-BLOCK %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -Wno-objc-root-class -fsyntax-only -ast-dump -ast-dump-filter test "-DSUBJECT=hasType(functionType)" %s | FileCheck --check-prefix=CHECK-HAS_TYPE_FUNCTION_TYPE %s + +#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(SUBJECT)) + +@interface testInterface +@end +// CHECK-OBJC_INTERFACE: ObjCInterfaceDecl{{.*}} testInterface +// CHECK-OBJC_INTERFACE-NEXT: AnnotateAttr{{.*}} "test" + +@interface testInterface () +@end +// CHECK-OBJC_INTERFACE: ObjCCategoryDecl +// CHECK-OBJC_INTERFACE-NOT: AnnotateAttr{{.*}} "test" +// CHECK-OBJC_CATEGORY: ObjCCategoryDecl +// CHECK-OBJC_CATEGORY-NEXT: ObjCInterface +// CHECK-OBJC_CATEGORY-NEXT: AnnotateAttr{{.*}} "test" + +@interface testInterface (testCategory) +@end +// CHECK-OBJC_INTERFACE: ObjCCategoryDecl{{.*}} testCategory +// CHECK-OBJC_INTERFACE-NOT: AnnotateAttr{{.*}} "test" +// CHECK-OBJC_CATEGORY: ObjCCategoryDecl{{.*}} testCategory +// CHECK-OBJC_CATEGORY-NEXT: ObjCInterface +// CHECK-OBJC_CATEGORY-NEXT: AnnotateAttr{{.*}} "test" + +// CHECK-OBJC_INTERFACE-LABEL: ObjCProtocolDecl +@protocol testProtocol +@end +// CHECK-OBJC_PROTOCOL: ObjCProtocolDecl{{.*}} testProtocol +// CHECK-OBJC_PROTOCOL-NEXT: AnnotateAttr{{.*}} "test" + +@interface methodContainer +- (void) testInstanceMethod; ++ (void) testClassMethod; +@end +// CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testInstanceMethod +// CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testClassMethod +// CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-OBJC_METHOD_IS_INSTANCE: ObjCMethodDecl{{.*}} testInstanceMethod +// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-OBJC_METHOD_IS_INSTANCE-LABEL: ObjCMethodDecl{{.*}} testClassMethod +// CHECK-OBJC_METHOD_IS_INSTANCE-NOT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: ObjCMethodDecl{{.*}} testInstanceMethod +// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: ObjCMethodDecl{{.*}} testClassMethod +// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" + +@implementation methodContainer +- (void) testInstanceMethod { } ++ (void) testClassMethod { } +@end +// CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testInstanceMethod +// CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD-NEXT: CompoundStmt +// CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testClassMethod +// CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD-NEXT: CompoundStmt +// CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-OBJC_METHOD_IS_INSTANCE-LABEL: ObjCMethodDecl{{.*}} testInstanceMethod +// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: CompoundStmt +// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-OBJC_METHOD_IS_INSTANCE: ObjCMethodDecl{{.*}} testClassMethod +// CHECK-OBJC_METHOD_IS_INSTANCE-NOT: AnnotateAttr{{.*}} "test" + +// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: ObjCMethodDecl{{.*}} testInstanceMethod +// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: ObjCMethodDecl{{.*}} testClassMethod +// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" +@interface propertyContainer { + int testIvar; +// CHECK-FIELD: ObjCIvarDecl{{.*}} testIvar +// CHECK-FIELD-NEXT: AnnotateAttr{{.*}} "test" + +} +@property int testProperty; +// CHECK-OBJC_PROPERTY: ObjCPropertyDecl{{.*}} testProperty +// CHECK-OBJC_PROPERTY-NEXT: AnnotateAttr{{.*}} "test" + +@end + +void (^testBlockVar)(); +// CHECK-BLOCK: VarDecl{{.*}} testBlockVar +// CHECK-BLOCK-NOT: AnnotateAttr{{.*}} "test" + +void testBlock() { + (void)(^ { }); +} +// CHECK-BLOCK-LABEL: BlockDecl +// CHECK-BLOCK-NEXT: CompoundStmt +// CHECK-BLOCK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE-LABEL: FunctionDecl{{.*}} testBlock +// CHECK-HAS_TYPE_FUNCTION_TYPE: BlockDecl +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: CompoundStmt +// The attribute applies to function, but not to block: +// CHECK-HAS_TYPE_FUNCTION_TYPE-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-HAS_TYPE_FUNCTION_TYPE-NOT: AnnotateAttr{{.*}} "test" + + +#pragma clang attribute pop diff --git a/clang/test/Misc/pragma-attribute-objc.m b/clang/test/Misc/pragma-attribute-objc.m new file mode 100644 index 00000000000..541cfa9ad3b --- /dev/null +++ b/clang/test/Misc/pragma-attribute-objc.m @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -fsyntax-only -Wno-objc-root-class -ast-dump -ast-dump-filter test %s | FileCheck %s + +#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(objc_interface, objc_protocol, objc_property, field, objc_method, variable)) +#pragma clang attribute push (__attribute__((objc_subclassing_restricted)), apply_to = objc_interface) + +@interface testInterface1 +// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testInterface1 +// CHECK-NEXT: ObjCImplementation +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: ObjCSubclassingRestrictedAttr{{.*}} + +// CHECK-NOT: AnnotateAttr +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +{ + int testIvar1; + // CHECK-LABEL: ObjCIvarDecl{{.*}} testIvar1 + // CHECK-NEXT: AnnotateAttr{{.*}} "test" + // CHECK-NOT: ObjCSubclassingRestrictedAttr +} + +@property int testProp1; +// CHECK-LABEL: ObjCPropertyDecl{{.*}} testProp1 +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +- (void)testIm:(int) x; +// CHECK-LABEL: ObjCMethodDecl{{.*}}testIm +// CHECK-NEXT: ParmVarDecl{{.*}} x +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr + ++ (void)testCm; +// CHECK-LABEL: ObjCMethodDecl{{.*}}testCm +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +// Implicit getters/setters shouldn't receive the attributes. +// CHECK-LABEL: ObjCMethodDecl{{.*}}testProp1 +// CHECK-NOT: AnnotateAttr +// CHECK-LABEL: ObjCMethodDecl{{.*}}setTestProp1 +// CHECK-NOT: AnnotateAttr + +@end + +// @implementation can't receive explicit attributes, so don't add the pragma +// attributes to them. +@implementation testInterface1 +// CHECK-LABEL: ObjCImplementationDecl{{.*}}testInterface1 +// CHECK-NOT: AnnotateAttr +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +{ + int testIvar2; + // CHECK-LABEL: ObjCIvarDecl{{.*}} testIvar2 + // CHECK-NEXT: AnnotateAttr{{.*}} "test" + // CHECK-NOT: ObjCSubclassingRestrictedAttr +} + +// Don't add attributes to implicit parameters! +- (void)testIm:(int) x { +// CHECK-LABEL: ObjCMethodDecl{{.*}}testIm +// CHECK-NEXT: ImplicitParamDecl +// CHECK-NEXT: ImplicitParamDecl +// CHECK-NEXT: ParmVarDecl{{.*}} x +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr +} + ++ (void)testCm { +// CHECK-LABEL: ObjCMethodDecl{{.*}}testCm +// CHECK: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr +// CHECK-NOT: AnnotateAttr + _Pragma("clang attribute push (__attribute__((annotate(\"applied at container start\"))), apply_to=objc_interface)"); +} + +// Implicit ivars shouldn't receive the attributes. +// CHECK-LABEL: ObjCIvarDecl{{.*}}_testProp1 +// CHECK-NOT: AnnotateAttr + +@end + +@implementation testImplWithoutInterface // expected-warning {{cannot find interface declaration for 'testImplWithoutInterface'}} +// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testImplWithoutInterface +// CHECK-NEXT: ObjCImplementation +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NEXT: ObjCSubclassingRestrictedAttr +// CHECK-NEXT: AnnotateAttr{{.*}} "applied at container start" + +// CHECK-LABEL: ObjCImplementationDecl{{.*}}testImplWithoutInterface +// CHECK-NOT: AnnotateAttr +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +@end + +#pragma clang attribute pop + +@protocol testProtocol +// CHECK-LABEL: ObjCProtocolDecl{{.*}}testProtocol +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr +// CHECK-NOT: AnnotateAttr + +- (void)testProtIm; +// CHECK-LABEL: ObjCMethodDecl{{.*}}testProtIm +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +@end + +@protocol testForwardProtocol; +// CHECK-LABEL: ObjCProtocolDecl{{.*}}testForwardProtocol +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr + + +// Categories can't receive explicit attributes, so don't add pragma attributes +// to them. +@interface testInterface1(testCat) +// CHECK-LABEL: ObjCCategoryDecl{{.*}}testCat +// CHECK-NOT: AnnotateAttr +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +@end + +@implementation testInterface1(testCat) +// CHECK-LABEL: ObjCCategoryImplDecl{{.*}}testCat +// CHECK-NOT: AnnotateAttr +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +@end + +// @class/@compatibility_alias declarations can't receive explicit attributes, +// so don't add pragma attributes to them. +@class testClass; +// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testClass +// CHECK-NOT: AnnotateAttr +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +@compatibility_alias testCompat testInterface1; +// CHECK-LABEL: ObjCCompatibleAliasDecl{{.*}}testCompat +// CHECK-NOT: AnnotateAttr +// CHECK-NOT: ObjCSubclassingRestrictedAttr + +#pragma clang attribute pop // objc_subclassing_restricted + +@interface testInterface3 +// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testInterface3 +// CHECK-NEXT: AnnotateAttr{{.*}} "test" +// CHECK-NOT: ObjCSubclassingRestrictedAttr +@end + +#pragma clang attribute pop // annotate("test") + +@interface testInterface4 +// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testInterface4 +// CHECK-NOT: AnnotateAttr +// CHECK-NOT: ObjCSubclassingRestrictedAttr +@end diff --git a/clang/test/Misc/pragma-attribute-strict-subjects.c b/clang/test/Misc/pragma-attribute-strict-subjects.c new file mode 100644 index 00000000000..ecd551bee6c --- /dev/null +++ b/clang/test/Misc/pragma-attribute-strict-subjects.c @@ -0,0 +1,222 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-pragma-clang-attribute -verify %s +// RUN: not %clang_cc1 -fsyntax-only -ast-dump -ast-dump-filter test %s | FileCheck %s + +// Check for contradictions in rules for attribute without a strict subject set: + +#pragma clang attribute push (__attribute__((annotate("subRuleContradictions"))), apply_to = any(variable, variable(is_parameter), function(is_member), variable(is_global))) +// expected-error@-1 {{redundant attribute subject matcher sub-rule 'variable(is_parameter)'; 'variable' already matches those declarations}} +// expected-error@-2 {{redundant attribute subject matcher sub-rule 'variable(is_global)'; 'variable' already matches those declarations}} + +// Ensure that we've recovered from the error: +int testRecoverSubRuleContradiction = 0; +// CHECK-LABEL: VarDecl{{.*}} testRecoverSubRuleContradiction +// CHECK-NEXT: IntegerLiteral +// CHECK-NEXT: AnnotateAttr{{.*}} "subRuleContradictions" + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions2"))), apply_to = any(variable(unless(is_parameter)), variable(is_thread_local), function, variable(is_global))) +// expected-error@-1 {{negated attribute subject matcher sub-rule 'variable(unless(is_parameter))' contradicts sub-rule 'variable(is_global)'}} +// We have just one error, don't error on 'variable(is_global)' + +// Ensure that we've recovered from the error: +int testRecoverNegatedContradiction = 0; +// CHECK-LABEL: VarDecl{{.*}} testRecoverNegatedContradiction +// CHECK-NEXT: IntegerLiteral +// CHECK-NEXT: AnnotateAttr{{.*}} "negatedSubRuleContradictions2" + +void testRecoverNegatedContradictionFunc(void); +// CHECK-LABEL: FunctionDecl{{.*}} testRecoverNegatedContradictionFunc +// CHECK-NEXT: AnnotateAttr{{.*}} "negatedSubRuleContradictions2" + +#pragma clang attribute pop + +// Verify the strict subject set verification. + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) + +int testRecoverStrictnessVar = 0; +// CHECK-LABEL: VarDecl{{.*}} testRecoverStrictnessVar +// CHECK-NEXT: IntegerLiteral +// CHECK-NOT: AbiTagAttr + +void testRecoverStrictnessFunc(void); +// CHECK-LABEL: FunctionDecl{{.*}} testRecoverStrictnessFunc +// CHECK-NEXT: AbiTagAttr + +struct testRecoverStrictnessStruct { }; +// CHECK-LABEL: RecordDecl{{.*}} testRecoverStrictnessStruct +// CHECK-NOT: AbiTagAttr + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) +// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} + +int testRecoverExtraVar = 0; +// CHECK-LABEL: VarDecl{{.*}} testRecoverExtraVar +// CHECK-NEXT: IntegerLiteral +// CHECK-NEXT: AbiTagAttr + +void testRecoverExtraFunc(void); +// CHECK-LABEL: FunctionDecl{{.*}} testRecoverExtraFunc +// CHECK-NEXT: AbiTagAttr + +struct testRecoverExtraStruct { }; +// CHECK-LABEL: RecordDecl{{.*}} testRecoverExtraStruct +// CHECK-NEXT: AbiTagAttr + +enum testNoEnumAbiTag { CaseCase }; +// CHECK-LABEL: EnumDecl{{.*}} testNoEnumAbiTag +// CHECK-NO: AbiTagAttr + +#pragma clang attribute pop + +// Verify the non-strict subject set verification. + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) + +int testSubset1Var; +// CHECK-LABEL: VarDecl{{.*}} testSubset1Var +// CHECK-NOT: AbiTagAttr + +void testSubset1Func(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubset1Func +// CHECK-NEXT: AbiTagAttr + +struct testSubset1Struct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubset1Struct +// CHECK-NOT: AbiTagAttr + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = variable) + +int testSubset2Var; +// CHECK-LABEL: VarDecl{{.*}} testSubset2Var +// CHECK-NEXT: AbiTagAttr + +void testSubset2Func(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubset2Func +// CHECK-NOT: AbiTagAttr + +struct testSubset2Struct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubset2Struct +// CHECK-NOT: AbiTagAttr + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)))) + +int testSubset3Var; +// CHECK-LABEL: VarDecl{{.*}} testSubset3Var +// CHECK-NOT: AbiTagAttr + +void testSubset3Func(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubset3Func +// CHECK-NOT: AbiTagAttr + +struct testSubset3Struct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubset3Struct +// CHECK-NEXT: AbiTagAttr + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable)) + +int testSubset4Var; +// CHECK-LABEL: VarDecl{{.*}} testSubset4Var +// CHECK-NEXT: AbiTagAttr + +void testSubset4Func(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubset4Func +// CHECK-NEXT: AbiTagAttr + +struct testSubset4Struct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubset4Struct +// CHECK-NOT: AbiTagAttr + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)))) + +int testSubset5Var; +// CHECK-LABEL: VarDecl{{.*}} testSubset5Var +// CHECK-NEXT: AbiTagAttr + +void testSubset5Func(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubset5Func +// CHECK-NOT: AbiTagAttr + +struct testSubset5Struct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubset5Struct +// CHECK-NEXT: AbiTagAttr + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function)) + +int testSubset6Var; +// CHECK-LABEL: VarDecl{{.*}} testSubset6Var +// CHECK-NOT: AbiTagAttr + +void testSubset6Func(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubset6Func +// CHECK-NEXT: AbiTagAttr + +struct testSubset6Struct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubset6Struct +// CHECK-NEXT: AbiTagAttr + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) + +int testSubset7Var; +// CHECK-LABEL: VarDecl{{.*}} testSubset7Var +// CHECK-NEXT: AbiTagAttr + +void testSubset7Func(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubset7Func +// CHECK-NEXT: AbiTagAttr + +struct testSubset7Struct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubset7Struct +// CHECK-NEXT: AbiTagAttr + +#pragma clang attribute pop + + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) +// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum_constant', and 'enum'}} + +int testSubsetRecoverVar; +// CHECK-LABEL: VarDecl{{.*}} testSubsetRecoverVar +// CHECK-NEXT: AbiTagAttr + +void testSubsetRecoverFunc(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubsetRecoverFunc +// CHECK-NEXT: AbiTagAttr + +struct testSubsetRecoverStruct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubsetRecoverStruct +// CHECK-NEXT: AbiTagAttr + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = enum) +// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} + +int testSubsetNoVar; +// CHECK-LABEL: VarDecl{{.*}} testSubsetNoVar +// CHECK-NOT: AbiTagAttr + +void testSubsetNoFunc(void); +// CHECK-LABEL: FunctionDecl{{.*}} testSubsetNoFunc +// CHECK-NOT: AbiTagAttr + +struct testSubsetNoStruct { }; +// CHECK-LABEL: RecordDecl{{.*}} testSubsetNoStruct +// CHECK-NOT: AbiTagAttr + +#pragma clang attribute pop diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test new file mode 100644 index 00000000000..b1f2e66ab33 --- /dev/null +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -0,0 +1,62 @@ +// RUN: clang-tblgen -gen-clang-test-pragma-attribute-supported-attributes -I%src_include_dir %src_include_dir/clang/Basic/Attr.td -o - | FileCheck %s + +// The number of supported attributes should never go down! + +// CHECK: #pragma clang attribute supports 57 attributes: +// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) +// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) +// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) +// CHECK-NEXT: AMDGPUWavesPerEU (SubjectMatchRule_function) +// CHECK-NEXT: AVRSignal (SubjectMatchRule_function) +// CHECK-NEXT: AbiTag (SubjectMatchRule_record_not_is_union, SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_namespace) +// CHECK-NEXT: AlignValue (SubjectMatchRule_variable, SubjectMatchRule_type_alias) +// CHECK-NEXT: AllocSize (SubjectMatchRule_function) +// CHECK-NEXT: Annotate () +// CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function) +// CHECK-NEXT: CXX11NoReturn (SubjectMatchRule_function) +// CHECK-NEXT: CallableWhen (SubjectMatchRule_function_is_member) +// CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function) +// CHECK-NEXT: Consumable (SubjectMatchRule_record) +// CHECK-NEXT: Convergent (SubjectMatchRule_function) +// CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) +// CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) +// CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method) +// CHECK-NEXT: EnableIf (SubjectMatchRule_function) +// CHECK-NEXT: EnumExtensibility (SubjectMatchRule_enum) +// CHECK-NEXT: FlagEnum (SubjectMatchRule_enum) +// CHECK-NEXT: Flatten (SubjectMatchRule_function) +// CHECK-NEXT: IFunc (SubjectMatchRule_function) +// CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) +// CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record) +// CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter) +// CHECK-NEXT: NoDuplicate (SubjectMatchRule_function) +// CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) +// CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) +// CHECK-NEXT: NoSplitStack (SubjectMatchRule_function) +// CHECK-NEXT: NotTailCalled (SubjectMatchRule_function) +// CHECK-NEXT: ObjCBoxable (SubjectMatchRule_record) +// CHECK-NEXT: ObjCMethodFamily (SubjectMatchRule_objc_method) +// CHECK-NEXT: ObjCRequiresSuper (SubjectMatchRule_objc_method) +// CHECK-NEXT: ObjCRuntimeName (SubjectMatchRule_objc_interface, SubjectMatchRule_objc_protocol) +// CHECK-NEXT: ObjCRuntimeVisible (SubjectMatchRule_objc_interface) +// CHECK-NEXT: ObjCSubclassingRestricted (SubjectMatchRule_objc_interface) +// CHECK-NEXT: OpenCLNoSVM (SubjectMatchRule_variable) +// CHECK-NEXT: OptimizeNone (SubjectMatchRule_function, SubjectMatchRule_objc_method) +// CHECK-NEXT: Overloadable (SubjectMatchRule_function) +// CHECK-NEXT: ParamTypestate (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) +// CHECK-NEXT: RequireConstantInit (SubjectMatchRule_variable_is_global) +// CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function) +// CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property) +// CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member) +// CHECK-NEXT: SwiftContext (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: SwiftErrorResult (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: SwiftIndirectResult (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: TLSModel (SubjectMatchRule_variable_is_thread_local) +// CHECK-NEXT: Target (SubjectMatchRule_function) +// CHECK-NEXT: TestTypestate (SubjectMatchRule_function_is_member) +// CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType) +// CHECK-NEXT: XRayInstrument (SubjectMatchRule_function_is_member, SubjectMatchRule_objc_method, SubjectMatchRule_function) +// CHECK-NEXT: XRayLogArgs (SubjectMatchRule_function_is_member, SubjectMatchRule_objc_method, SubjectMatchRule_function) diff --git a/clang/test/Parser/pragma-attribute-declspec.cpp b/clang/test/Parser/pragma-attribute-declspec.cpp new file mode 100644 index 00000000000..28785ba9006 --- /dev/null +++ b/clang/test/Parser/pragma-attribute-declspec.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple i386-pc-win32 -std=c++11 -verify -Wno-pragma-clang-attribute -fms-extensions -fms-compatibility %s + +#pragma clang attribute push(__declspec(dllexport), apply_to = function) + +void function(); + +#pragma clang attribute pop + +#pragma clang attribute push(__declspec(dllexport, dllimport), apply_to = function) // expected-error {{more than one attribute specified in '#pragma clang attribute push'}} + +#pragma clang attribute push(__declspec(align), apply_to = variable) // expected-error {{attribute 'align' is not supported by '#pragma clang attribute'}} + +#pragma clang attribute push(__declspec(), apply_to = variable) // A noop diff --git a/clang/test/Parser/pragma-attribute.cpp b/clang/test/Parser/pragma-attribute.cpp new file mode 100644 index 00000000000..b28ec8c2c86 --- /dev/null +++ b/clang/test/Parser/pragma-attribute.cpp @@ -0,0 +1,181 @@ +// RUN: %clang_cc1 -Wno-pragma-clang-attribute -verify -std=c++11 %s + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = function) + +void function(); + +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(variable(is_parameter), function)) +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = variable(unless(is_parameter))) +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(variable(unless(is_parameter)))) +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a")))) // expected-error {{expected ','}} +#pragma clang attribute push (__attribute__((abi_tag("a"))) apply_to=function) // expected-error {{expected ','}} +#pragma clang attribute push (__attribute__((abi_tag("a"))) = function) // expected-error {{expected ','}} +#pragma clang attribute push (__attribute__((abi_tag("a"))) any(function)) // expected-error {{expected ','}} + +#pragma clang attribute push (__attribute__((abi_tag("a"))) 22) // expected-error {{expected ','}} +#pragma clang attribute push (__attribute__((abi_tag("a"))) function) // expected-error {{expected ','}} +#pragma clang attribute push (__attribute__((abi_tag("a"))) (function)) // expected-error {{expected ','}} + +#pragma clang attribute push(__attribute__((annotate("test"))), ) // expected-error {{expected attribute subject set specifier 'apply_to'}} +#pragma clang attribute push(__attribute__((annotate("test"))), = any(function)) // expected-error {{expected attribute subject set specifier 'apply_to'}} +#pragma clang attribute push(__attribute__((annotate("test"))), = function) // expected-error {{expected attribute subject set specifier 'apply_to'}} +#pragma clang attribute push(__attribute__((annotate("test"))), any(function)) // expected-error {{expected attribute subject set specifier 'apply_to'}} +#pragma clang attribute push(__attribute__((annotate("test"))), function) // expected-error {{expected attribute subject set specifier 'apply_to'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply = any(function )) // expected-error {{expected attribute subject set specifier 'apply_to'}} +#pragma clang attribute push(__attribute__((annotate("test"))), to = function) // expected-error {{expected attribute subject set specifier 'apply_to'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_only_to = function) // expected-error {{expected attribute subject set specifier 'apply_to'}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to any(function)) // expected-error {{expected '='}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to function) // expected-error {{expected '='}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to) // expected-error {{expected '='}} +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to 41 (22)) // expected-error {{expected '='}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any) // expected-error {{expected '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any {) // expected-error {{expected '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any function) // expected-error {{expected '('}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = { function, enum }) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function ) // expected-error {{expected ')'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(function, )) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, enum ) // expected-error {{expected ')'}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = () ) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( + ) ) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any()) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, 42 )) // expected-error {{expected an identifier that corresponds to an attribute subject rule}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( diag )) // expected-error {{unknown attribute subject rule 'diag'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( a )) // expected-error {{unknown attribute subject rule 'a'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, for)) // expected-error {{unknown attribute subject rule 'for'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function42, for )) // expected-error {{unknown attribute subject rule 'function42'}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(hasType)) // expected-error {{expected '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = hasType) // expected-error {{expected '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = hasType(functionType)) // OK + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable( )) // expected-error {{expected ')'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable( ) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is ) )) // expected-error {{unknown attribute subject matcher sub-rule 'is'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_parameter, not) )) // expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable is_parameter )) // expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable ( ) // expected-error {{expected ')'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = variable ( // expected-error {{expected ')'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (is ()) )) // expected-error {{unknown attribute subject matcher sub-rule 'is'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (42) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, namespace("test") )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'namespace' matcher does not support sub-rules}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable ("test" )) // expected-error {{expected ')'}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = enum(is_parameter)) // expected-error {{invalid use of attribute subject matcher sub-rule 'is_parameter'; 'enum' matcher does not support sub-rules}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any(enum(is_parameter))) // expected-error {{invalid use of attribute subject matcher sub-rule 'is_parameter'; 'enum' matcher does not support sub-rules}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any (function, variable (unless) )) // expected-error {{expected '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any (function, variable (unless() )) // expected-error {{expected ')'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any ( function, variable (unless(is)) )) // expected-error {{unknown attribute subject matcher sub-rule 'unless(is)'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter, not)) )) // expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter), not) ) // expected-error {{expected ')'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable unless is_parameter )) // expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless is_parameter) )) // expected-error {{expected '('}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (unless(42)) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, enum(unless("test")) )) // expected-error {{expected an identifier that corresponds to an attribute subject matcher sub-rule; 'enum' matcher does not support sub-rules}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, variable (unless(is_global)) )) // expected-error {{unknown attribute subject matcher sub-rule 'unless(is_global)'; 'variable' matcher supports the following sub-rules: 'is_thread_local', 'is_global', 'is_parameter', 'unless(is_parameter)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( enum(unless(is_parameter)) )) // expected-error {{invalid use of attribute subject matcher sub-rule 'unless(is_parameter)'; 'enum' matcher does not support sub-rules}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, function )) // expected-error {{duplicate attribute subject matcher 'function'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, function, function )) // expected-error 2 {{duplicate attribute subject matcher 'function'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( function, enum, function )) // expected-error {{duplicate attribute subject matcher 'function'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( enum, enum, function )) // expected-error {{duplicate attribute subject matcher 'enum'}} + +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_global), variable(is_global) )) // expected-error {{duplicate attribute subject matcher 'variable(is_global)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(is_global), function, variable(is_global), variable(is_global) )) // expected-error 2 {{duplicate attribute subject matcher 'variable(is_global)'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter)), variable(unless(is_parameter)) )) // expected-error {{duplicate attribute subject matcher 'variable(unless(is_parameter))'}} +#pragma clang attribute push(__attribute__((annotate("test"))), apply_to = any( variable(unless(is_parameter)), variable(unless(is_parameter)), enum, variable(unless(is_parameter)) )) // expected-error 2 {{duplicate attribute subject matcher 'variable(unless(is_parameter))'}} + +#pragma clang attribute // expected-error {{expected 'push' or 'pop' after '#pragma clang attribute'}} +#pragma clang attribute 42 // expected-error {{expected 'push' or 'pop' after '#pragma clang attribute'}} +#pragma clang attribute pushpop // expected-error {{unexpected argument 'pushpop' to '#pragma clang attribute'; expected 'push' or 'pop'}} + +#pragma clang attribute push // expected-error {{expected '('}} +#pragma clang attribute push ( // expected-error {{expected an attribute after '('}} +#pragma clang attribute push (__attribute__((annotate)) // expected-error {{expected ')'}} +#pragma clang attribute push () // expected-error {{expected an attribute after '('}} + +#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = function) () // expected-warning {{extra tokens at end of '#pragma clang attribute'}} +// expected-error@-1 {{expected unqualified-id}} +// expected-error@-2 {{unterminated '#pragma clang attribute push' at end of file}} + +#pragma clang attribute pop () // expected-warning {{extra tokens at end of '#pragma clang attribute'}} + +; + +#pragma clang attribute push (__attribute__((42))) // expected-error {{expected identifier that represents an attribute name}} + +#pragma clang attribute push (__attribute__((annotate)) foo) // expected-error {{expected ','}} +#pragma clang attribute push (__attribute__((annotate)), apply_to=function foo) // expected-error {{extra tokens after attribute in a '#pragma clang attribute push'}} + +#pragma clang attribute push (__attribute__((availability(macos, foo=1))), apply_to=function) // expected-error {{'foo' is not an availability stage; use 'introduced', 'deprecated', or 'obsoleted'}} +// expected-error@-1 {{attribute 'availability' is not supported by '#pragma clang attribute'}} +#pragma clang attribute push (__attribute__((availability(macos, 1))), apply_to=function) // expected-error {{expected 'introduced', 'deprecated', or 'obsoleted'}} + +#pragma clang attribute push (__attribute__((used)), apply_to=function) // expected-error {{attribute 'used' is not supported by '#pragma clang attribute'}} + +void statementPragmasAndPragmaExpression() { +#pragma clang attribute push (__attribute__((annotate("hello"))), apply_to=variable) +#pragma clang attribute pop +int x = 0; +_Pragma("clang attribute push (__attribute__((annotate(\"hi\"))), apply_to = function)"); + +_Pragma("clang attribute push (__attribute__((annotate(\"hi\"))), apply_to = any(function(is_method ))"); // expected-error {{expected ')'}} +} + +_Pragma("clang attribute pop"); + +#pragma clang attribute push (__attribute__((address_space(0))), apply_to=variable) // expected-error {{attribute 'address_space' is not supported by '#pragma clang attribute'}} + +// Check support for CXX11 style attributes +#pragma clang attribute push ([[noreturn]], apply_to = any(function)) +#pragma clang attribute pop + +#pragma clang attribute push ([[clang::disable_tail_calls]], apply_to = function) +#pragma clang attribute pop + +#pragma clang attribute push ([[gnu::abi_tag]], apply_to=any(function)) +#pragma clang attribute pop + +#pragma clang attribute push ([[clang::disable_tail_calls, noreturn]], apply_to = function) // expected-error {{more than one attribute specified in '#pragma clang attribute push'}} +#pragma clang attribute push ([[clang::disable_tail_calls, noreturn]]) // expected-error {{more than one attribute specified in '#pragma clang attribute push'}} + +#pragma clang attribute push ([[gnu::abi_tag]], apply_to=namespace) +#pragma clang attribute pop + +#pragma clang attribute push ([[fallthrough]], apply_to=function) // expected-error {{attribute 'fallthrough' is not supported by '#pragma clang attribute'}} +#pragma clang attribute push ([[clang::fallthrough]], apply_to=function) // expected-error {{attribute 'fallthrough' is not supported by '#pragma clang attribute'}} + +#pragma clang attribute push ([[]], apply_to = function) // A noop + +#pragma clang attribute push ([[noreturn ""]], apply_to=function) // expected-error {{expected ']'}} +#pragma clang attribute pop +#pragma clang attribute push ([[noreturn 42]]) // expected-error {{expected ']'}} expected-error {{expected ','}} + +#pragma clang attribute push(__attribute__, apply_to=function) // expected-error {{expected '(' after 'attribute'}} +#pragma clang attribute push(__attribute__(), apply_to=function) // expected-error {{expected '(' after '('}} +#pragma clang attribute push(__attribute__(()), apply_to=function) // expected-error {{expected identifier that represents an attribute name}} +#pragma clang attribute push(__attribute__((annotate, apply_to=function))) // expected-error {{expected ')'}} +#pragma clang attribute push(__attribute__((annotate("test"), apply_to=function))) // expected-error {{expected ')'}} +#pragma clang attribute push(__attribute__((annotate), apply_to=function)) // expected-error {{expected ')'}} + +#pragma clang attribute push (42) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} +#pragma clang attribute push (test) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} +#pragma clang attribute push (annotate) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} +// expected-note@-1 {{use the GNU '__attribute__' syntax}} +#pragma clang attribute push (annotate("test")) // expected-error {{expected an attribute that is specified using the GNU, C++11 or '__declspec' syntax}} +// expected-note@-1 {{use the GNU '__attribute__' syntax}} diff --git a/clang/test/Sema/pragma-attribute-strict-subjects.c b/clang/test/Sema/pragma-attribute-strict-subjects.c new file mode 100644 index 00000000000..a84e2bde38d --- /dev/null +++ b/clang/test/Sema/pragma-attribute-strict-subjects.c @@ -0,0 +1,153 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-pragmas -verify %s + +#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(function, variable)) + +#pragma clang attribute pop + +// Check for contradictions in rules for attribute without a strict subject set: + +#pragma clang attribute push (__attribute__((annotate("subRuleContradictions"))), apply_to = any(variable, variable(is_parameter), function(is_member), variable(is_global))) +// expected-error@-1 {{redundant attribute subject matcher sub-rule 'variable(is_parameter)'; 'variable' already matches those declarations}} +// expected-error@-2 {{redundant attribute subject matcher sub-rule 'variable(is_global)'; 'variable' already matches those declarations}} + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("subRuleContradictions2"))), apply_to = any(function(is_member), function)) +// expected-error@-1 {{redundant attribute subject matcher sub-rule 'function(is_member)'; 'function' already matches those declarations}} + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("subRuleContradictions3"))), apply_to = any(variable, variable(unless(is_parameter)))) +// expected-error@-1 {{redundant attribute subject matcher sub-rule 'variable(unless(is_parameter))'; 'variable' already matches those declarations}} + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions1"))), apply_to = any(variable(is_parameter), variable(unless(is_parameter)))) +// expected-error@-1 {{negated attribute subject matcher sub-rule 'variable(unless(is_parameter))' contradicts sub-rule 'variable(is_parameter)'}} + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("negatedSubRuleContradictions2"))), apply_to = any(variable(unless(is_parameter)), variable(is_thread_local), function, variable(is_global))) +// expected-error@-1 {{negated attribute subject matcher sub-rule 'variable(unless(is_parameter))' contradicts sub-rule 'variable(is_global)'}} +// We have just one error, don't error on 'variable(is_global)' + +#pragma clang attribute pop + +// Verify the strict subject set verification. + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) +// No error +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) +// No error +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable, record(unless(is_union)))) +// No error +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)), function)) +// No error +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) +// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(enum_constant, function, record(unless(is_union)), variable, variable(is_parameter))) +// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'variable(is_parameter)', and 'enum_constant'}} +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), enum)) +// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} +#pragma clang attribute pop + +// Verify the non-strict subject set verification. + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function)) + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = variable) + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)))) + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, variable)) + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(variable, record(unless(is_union)))) + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function)) + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable)) + +#pragma clang attribute pop + + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) +// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum_constant', and 'enum'}} + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = enum) +// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} + +#pragma clang attribute pop + +// Handle attributes whose subjects are supported only in other language modes: + +#pragma clang attribute push(__attribute__((abi_tag("b"))), apply_to = any(namespace, record(unless(is_union)), variable, function)) +// 'namespace' is accepted! +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((abi_tag("b"))), apply_to = any(namespace)) +// 'namespace' is accepted! +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = objc_interface) +// No error! +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = objc_interface) +// No error! +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_interface, objc_protocol)) +// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_protocol)) +// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} +// Don't report an error about missing 'objc_interface' as we aren't parsing +// Objective-C. +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_interface, objc_protocol)) +// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} +#pragma clang attribute pop + +#pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_protocol)) +// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} +// Don't report an error about missing 'objc_interface' as we aren't parsing +// Objective-C. +#pragma clang attribute pop + +// Use of matchers from other language modes should not cause for attributes +// without subject list: +#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = objc_method) + +#pragma clang attribute pop + +#pragma clang attribute push (__attribute__((annotate("test"))), apply_to = any(objc_interface, objc_protocol)) + +#pragma clang attribute pop diff --git a/clang/test/Sema/pragma-attribute.c b/clang/test/Sema/pragma-attribute.c new file mode 100644 index 00000000000..d321f2ce4be --- /dev/null +++ b/clang/test/Sema/pragma-attribute.c @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#pragma clang attribute pop // expected-error {{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}} + +// Don't verify unused attributes. +#pragma clang attribute push (__attribute__((annotate)), apply_to = function) // expected-warning {{unused attribute 'annotate' in '#pragma clang attribute push' region}} +#pragma clang attribute pop // expected-note {{'#pragma clang attribute push' regions ends here}} + +// Ensure we only report any errors once. +#pragma clang attribute push (__attribute__((annotate)), apply_to = function) // expected-error 4 {{'annotate' attribute takes one argument}} + +void test5_begin(); // expected-note {{when applied to this declaration}} +void test5_1(); // expected-note {{when applied to this declaration}} + +#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error 2 {{'annotate' attribute takes one argument}} + +void test5_2(); // expected-note 2 {{when applied to this declaration}} + +#pragma clang attribute push (__attribute__((annotate("hello", "world"))), apply_to = function) // expected-error {{'annotate' attribute takes one argument}} + +void test5_3(); // expected-note 3 {{when applied to this declaration}} + +#pragma clang attribute pop +#pragma clang attribute pop +#pragma clang attribute pop + +// Verify that the warnings are reported for each receiver declaration + +#pragma clang attribute push (__attribute__((optnone)), apply_to = function) // expected-note 2 {{conflicting attribute is here}} + +__attribute__((always_inline)) void optnone1() { } // expected-warning {{'always_inline' attribute ignored}} +// expected-note@-1 {{when applied to this declaration}} + +void optnone2() { } + +__attribute__((always_inline)) void optnone3() { } // expected-warning {{'always_inline' attribute ignored}} +// expected-note@-1 {{when applied to this declaration}} + +#pragma clang attribute pop + +#pragma clang attribute push ([[]], apply_to = function) // A noop + +#pragma clang attribute pop // expected-error {{'#pragma clang attribute pop' with no matching '#pragma clang attribute push'}} + +#pragma clang attribute push (__attribute__((annotate("func"))), apply_to = function) // expected-error {{unterminated '#pragma clang attribute push' at end of file}} + +void function(); diff --git a/clang/test/lit.cfg b/clang/test/lit.cfg index e4a13054ba8..a5e8b9de994 100644 --- a/clang/test/lit.cfg +++ b/clang/test/lit.cfg @@ -284,6 +284,8 @@ if config.host_triple and config.host_triple != '@LLVM_HOST_TRIPLE@': else: config.substitutions.append( ('%target_itanium_abi_host_triple', '') ) +config.substitutions.append( ('%src_include_dir', config.clang_src_dir + '/include') ) + # FIXME: Find nicer way to prohibit this. config.substitutions.append( (' clang ', """*** Do not use 'clang' in tests, use '%clang'. ***""") ) diff --git a/clang/test/lit.site.cfg.in b/clang/test/lit.site.cfg.in index 8fdfbfc4842..63d71398748 100644 --- a/clang/test/lit.site.cfg.in +++ b/clang/test/lit.site.cfg.in @@ -10,6 +10,7 @@ config.llvm_shlib_dir = "@SHLIBDIR@" config.llvm_plugin_ext = "@LLVM_PLUGIN_EXT@" config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" config.clang_obj_root = "@CLANG_BINARY_DIR@" +config.clang_src_dir = "@CLANG_SOURCE_DIR@" config.clang_tools_dir = "@CLANG_TOOLS_DIR@" config.host_triple = "@LLVM_HOST_TRIPLE@" config.target_triple = "@TARGET_TRIPLE@" |