diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -144,6 +144,9 @@ [{S->getFunctionType(false) != nullptr}], "functions, function pointers">; +def FunctionDef : SubsetSubjectisThisDeclarationADefinition()}], + "function definitions">; + def OpenCLKernelFunction : SubsetSubjecthasAttr()}], "kernel functions">; @@ -2344,7 +2347,7 @@ def ArmLocallyStreaming : DeclOrTypeAttr, TargetSpecificAttr { let Spellings = [Clang<"arm_locally_streaming">]; - let Subjects = SubjectList<[Function], ErrorDiag>; + let Subjects = SubjectList<[FunctionDef], ErrorDiag>; let Documentation = [ArmSmeLocallyStreamingDocs]; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9826,8 +9826,18 @@ } } - // Handle attributes. - ProcessDeclAttributes(S, NewFD, D); + // Because not all of the declaration may have been parsed at the point of + // calling this function, we forcably toggle 'WillHaveBody' if we're parsing + // a function definition so that the code handling the attributes can check + // whether the attribute is applied on the correct construct. We also reset + // the 'WillHaveBody' value, because other places in Clang assume this hasn't + // already been set. + if (D.isFunctionDefinition()) { + NewFD->setWillHaveBody(); + ProcessDeclAttributes(S, NewFD, D); + NewFD->setWillHaveBody(false); + } else + ProcessDeclAttributes(S, NewFD, D); if (getLangOpts().OpenCL) { // OpenCL v1.1 s6.5: Using an address space qualifier in a function return diff --git a/clang/test/AST/ast-dump-wasm-attr-export.c b/clang/test/AST/ast-dump-wasm-attr-export.c --- a/clang/test/AST/ast-dump-wasm-attr-export.c +++ b/clang/test/AST/ast-dump-wasm-attr-export.c @@ -10,24 +10,21 @@ // Test that functions can be redeclared and they retain their attributes. -__attribute__((export_name("export_red"))) void red(void) {} -__attribute__((export_name("export_orange"))) void orange(void) {} -__attribute__((export_name("export_yellow"))) void yellow(void) {} +__attribute__((export_name("export_red"))) void red(void); +__attribute__((export_name("export_orange"))) void orange(void); +__attribute__((export_name("export_yellow"))) void yellow(void); void red(void); void orange(void); void yellow(void); // CHECK: |-FunctionDecl {{.+}} used red 'void (void)' -// CHECK: | |-CompoundStmt {{.+}} // CHECK: | |-WebAssemblyExportNameAttr {{.+}} "export_red" // CHECK: | `-UsedAttr {{.+}} Implicit // CHECK: |-FunctionDecl {{.+}} used orange 'void (void)' -// CHECK: | |-CompoundStmt {{.+}} // CHECK: | |-WebAssemblyExportNameAttr {{.+}} "export_orange" // CHECK: | `-UsedAttr {{.+}} Implicit // CHECK: |-FunctionDecl {{.+}} used yellow 'void (void)' -// CHECK: | |-CompoundStmt {{.+}} // CHECK: | |-WebAssemblyExportNameAttr {{.+}} "export_yellow" // CHECK: | `-UsedAttr {{.+}} Implicit // CHECK: |-FunctionDecl {{.+}} used red 'void (void)' diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -18,7 +18,6 @@ // CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType) // CHECK-NEXT: ArcWeakrefUnavailable (SubjectMatchRule_objc_interface) // CHECK-NEXT: ArmBuiltinAlias (SubjectMatchRule_function) -// CHECK-NEXT: ArmLocallyStreaming (SubjectMatchRule_function) // CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function) // CHECK-NEXT: Assumption (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_implementation, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable)) diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -100,6 +100,10 @@ // expected-note@+1 {{conflicting attribute is here}} __attribute__((arm_preserves_za, arm_new_za)) void preserves_new_za(void); +// expected-cpp-error@+2 {{'arm_locally_streaming' attribute only applies to function definitions}} +// expected-error@+1 {{'arm_locally_streaming' attribute only applies to function definitions}} +__attribute__((arm_locally_streaming)) void sme_arm_locally_streaming_on_declaration(void); + // Invalid attributes on function pointers // expected-cpp-error@+4 {{'arm_streaming_compatible' and 'arm_streaming' attributes are not compatible}} @@ -138,8 +142,8 @@ typedef __attribute__((arm_new_za, arm_preserves_za)) void (*fptrty10) (void); fptrty10 invalid_preserve_za_func() { return preserves_za_ptr_invalid; } -// expected-cpp-error@+2 {{'arm_locally_streaming' attribute only applies to functions}} -// expected-error@+1 {{'arm_locally_streaming' attribute only applies to functions}} +// expected-cpp-error@+2 {{'arm_locally_streaming' attribute only applies to function definitions}} +// expected-error@+1 {{'arm_locally_streaming' attribute only applies to function definitions}} typedef __attribute__((arm_locally_streaming)) void (*fptrty11) (void); // expected-warning@+2 {{'arm_streaming' attribute ignored}}