diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index eb8b1352d1be1..5e2d22f910d04 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5421,6 +5421,31 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs(), S.CUDA().IdentifyTarget(D.getAttributes())); + // Handle attributes on the declaration specifier that were deferred up + // until now when we have the full type of the declarator. + if (D.getContext() == DeclaratorContext::AliasDecl) { + CUDAFunctionTarget CFT = + S.CUDA().IdentifyTarget(D.getDeclSpec().getAttributes()); + for (ParsedAttr &attr : D.getDeclSpec().getAttributes()) { + if (!(attr.isStandardAttributeSyntax() || + attr.isRegularKeywordAttribute()) || + !attr.isTypeAttr() || !attr.isUsedAsTypeAttr()) + continue; + + switch (attr.getKind()) { + FUNCTION_TYPE_ATTRS_CASELIST: { + if (!handleFunctionTypeAttr(state, attr, T, CFT)) { + diagnoseBadTypeAttribute(state.getSema(), attr, T); + attr.setInvalid(); + } + break; + } + default: + break; + } + } + } + if (DeclType.Kind != DeclaratorChunk::Paren) { if (ExpectNoDerefChunk && !IsNoDerefableChunk(DeclType)) S.Diag(DeclType.Loc, diag::warn_noderef_on_non_pointer_or_array); @@ -9078,7 +9103,14 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // appertain to and hence should not use the "distribution" logic below. if (attr.isStandardAttributeSyntax() || attr.isRegularKeywordAttribute()) { - if (!handleFunctionTypeAttr(state, attr, type, CFT)) { + // If we are in a C++ type alias via `using` where the attribute is + // placed after the alias name but before the `=`, the type here may + // refer to just the return type of a function rather than the function + // as a whole. In this specific case, defer handling the function type + // attribute until we have the full type of the declarator. + bool InAliasDecl = + state.getDeclarator().getContext() == DeclaratorContext::AliasDecl; + if (!handleFunctionTypeAttr(state, attr, type, CFT) && !InAliasDecl) { diagnoseBadTypeAttribute(state.getSema(), attr, type); attr.setInvalid(); } diff --git a/clang/test/AST/cfi-unchecked-callee.cpp b/clang/test/AST/cfi-unchecked-callee.cpp index af84996835930..9bce8c1aa660c 100644 --- a/clang/test/AST/cfi-unchecked-callee.cpp +++ b/clang/test/AST/cfi-unchecked-callee.cpp @@ -7,3 +7,6 @@ void func(void); // CHECK-NEXT: FunctionDecl {{0x[a-z0-9]*}} prev [[PTR]] {{.*}}func 'void () __attribute__((cfi_unchecked_callee))' void func(void) {} + +// CHECK: TypeAliasDecl {{0x[a-z0-9]*}} {{.*}}CfiCheckFunction 'void () __attribute__((cfi_unchecked_callee))' +using CfiCheckFunction [[clang::cfi_unchecked_callee]] = void(void); diff --git a/clang/test/AST/regparm.cpp b/clang/test/AST/regparm.cpp new file mode 100644 index 0000000000000..0dc3fcfb717f3 --- /dev/null +++ b/clang/test/AST/regparm.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -ast-dump %s | FileCheck %s + +// CHECK: TypeAliasDecl {{0x[a-z0-9]*}} {{.*}}T1 'void (int) __attribute__((regparm (2)))' +using T1 [[gnu::regparm(2)]] = void(int); diff --git a/clang/test/Frontend/cfi-unchecked-callee-attribute.cpp b/clang/test/Frontend/cfi-unchecked-callee-attribute.cpp index a5a17dd5a4d82..4c0b5fe882ac3 100644 --- a/clang/test/Frontend/cfi-unchecked-callee-attribute.cpp +++ b/clang/test/Frontend/cfi-unchecked-callee-attribute.cpp @@ -238,3 +238,5 @@ void lambdas() { CFI_UNCHECKED_CALLEE void func(void); void func(void) {} // No warning expected. + +using CfiCheckFunction [[clang::cfi_unchecked_callee]] = void(void* entry, const void* diag_data); diff --git a/clang/test/Frontend/regparm.cpp b/clang/test/Frontend/regparm.cpp new file mode 100644 index 0000000000000..d1416116be3f7 --- /dev/null +++ b/clang/test/Frontend/regparm.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown %s -verify +// expected-no-diagnostics + +using T1 [[gnu::regparm(2)]] = void(int); diff --git a/clang/test/Parser/cxx0x-keyword-attributes.cpp b/clang/test/Parser/cxx0x-keyword-attributes.cpp index be7423cc7ecee..70b6d0acb615a 100644 --- a/clang/test/Parser/cxx0x-keyword-attributes.cpp +++ b/clang/test/Parser/cxx0x-keyword-attributes.cpp @@ -137,10 +137,10 @@ using ATTR_USE alignas(4)ATTR_USE ns::i; // expected-warning 2 {{ISO C+ expected-error 2 {{'ATTR_NAME' only applies to non-K&R-style functions}} using ATTR_USE alignas(4) ATTR_USE foobar = int; // expected-error {{'ATTR_NAME' cannot appear here}} \ expected-error {{'alignas' attribute only applies to}} \ - expected-error 2 {{'ATTR_NAME' only applies to function types}} + expected-error 2 {{'ATTR_NAME' only applies to non-K&R-style functions}} ATTR_USE using T = int; // expected-error {{'ATTR_NAME' cannot appear here}} -using T ATTR_USE = int; // expected-error {{'ATTR_NAME' only applies to function types}} +using T ATTR_USE = int; // expected-error {{'ATTR_NAME' only applies to non-K&R-style functions}} template using U ATTR_USE = T; // expected-error {{'ATTR_NAME' only applies to function types}} using ns::i ATTR_USE; // expected-warning {{ISO C++}} \ expected-error {{'ATTR_NAME' only applies to non-K&R-style functions}} @@ -162,7 +162,7 @@ struct using_in_struct : using_in_struct_base { using ATTR_USE ns::i; // expected-warning {{ISO C++}} \ expected-error {{'ATTR_NAME' cannot appear here}} \ expected-error {{'ATTR_NAME' only applies to non-K&R-style functions}} -using T ATTR_USE = int; // expected-error {{'ATTR_NAME' only applies to function types}} +using T ATTR_USE = int; // expected-error {{'ATTR_NAME' only applies to non-K&R-style functions}} auto trailing() -> ATTR_USE const int; // expected-error {{'ATTR_NAME' cannot appear here}} auto trailing() -> const ATTR_USE int; // expected-error {{'ATTR_NAME' cannot appear here}}