diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7ff9c2754a6fe..6931f50202162 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4453,9 +4453,10 @@ class Sema final : public SemaBase { SourceLocation *ArgLocation = nullptr); /// Determine if type T is a valid subject for a nonnull and similar - /// attributes. By default, we look through references (the behavior used by - /// nonnull), but if the second parameter is true, then we treat a reference - /// type as valid. + /// attributes. Dependent types are considered valid so they can be checked + /// during instantiation time. By default, we look through references (the + /// behavior used by nonnull), but if the second parameter is true, then we + /// treat a reference type as valid. bool isValidPointerAttrType(QualType T, bool RefOkay = false); /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index af983349a89b5..e2174ba926f17 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1216,6 +1216,8 @@ static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) { } bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) { + if (T->isDependentType()) + return true; if (RefOkay) { if (T->isReferenceType()) return true; @@ -1284,7 +1286,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E && !AnyPointers; ++I) { QualType T = getFunctionOrMethodParamType(D, I); - if (T->isDependentType() || S.isValidPointerAttrType(T)) + if (S.isValidPointerAttrType(T)) AnyPointers = true; } @@ -1409,8 +1411,7 @@ void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI, AllocAlignAttr TmpAttr(Context, CI, ParamIdx()); SourceLocation AttrLoc = CI.getLoc(); - if (!ResultType->isDependentType() && - !isValidPointerAttrType(ResultType, /* RefOkay */ true)) { + if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) { Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only) << &TmpAttr << CI.getRange() << getFunctionOrMethodResultSourceRange(D); return; diff --git a/clang/test/SemaCXX/alloc-align-attr.cpp b/clang/test/SemaCXX/alloc-align-attr.cpp index 79095f8d98514..5a40e8d8fb6b5 100644 --- a/clang/test/SemaCXX/alloc-align-attr.cpp +++ b/clang/test/SemaCXX/alloc-align-attr.cpp @@ -23,6 +23,9 @@ void* dependent_param_func(T param) __attribute__((alloc_align(1)));// expected- template void* illegal_align_param(int p) __attribute__((alloc_align(T))); // expected-error {{'alloc_align' attribute requires parameter 1 to be an integer constant}} +template +T dependent_return_type(int p) __attribute__((alloc_align(1))); + void dependent_impl(int align) { dependent_ret a; // expected-note {{in instantiation of template class 'dependent_ret' requested here}} a.Foo(1); diff --git a/clang/test/SemaCXX/builtin-assume-aligned-tmpl.cpp b/clang/test/SemaCXX/builtin-assume-aligned-tmpl.cpp index 61b85557d6b29..e709c936735c7 100644 --- a/clang/test/SemaCXX/builtin-assume-aligned-tmpl.cpp +++ b/clang/test/SemaCXX/builtin-assume-aligned-tmpl.cpp @@ -52,6 +52,12 @@ T *atest3() __attribute__((assume_aligned(31, o))); // expected-error {{requeste template T *atest4() __attribute__((assume_aligned(32, o))); +template +T atest5(int) __attribute__((assume_aligned(2))); + +// expected-warning@+1 {{'assume_aligned' attribute only applies to return values that are pointers or references}} +int atest6(int) __attribute__((assume_aligned(2))); + void test22() { atest3(); atest4(); diff --git a/clang/test/SemaCXX/noescape-attr.cpp b/clang/test/SemaCXX/noescape-attr.cpp new file mode 100644 index 0000000000000..78dc4f07ffef8 --- /dev/null +++ b/clang/test/SemaCXX/noescape-attr.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template +void test1(T __attribute__((noescape)) arr, int size); + +// expected-warning@+1 {{'noescape' attribute only applies to pointer arguments}} +void test2(int __attribute__((noescape)) arr, int size); \ No newline at end of file diff --git a/clang/test/SemaObjCXX/noescape.mm b/clang/test/SemaObjCXX/noescape.mm index 4b52164dffd3d..999a91b87300b 100644 --- a/clang/test/SemaObjCXX/noescape.mm +++ b/clang/test/SemaObjCXX/noescape.mm @@ -17,7 +17,7 @@ void noescapeFunc2(int *); // expected-error {{conflicting types for 'noescapeFunc2'}} template -void noescapeFunc5(__attribute__((noescape)) T); // expected-warning {{'noescape' attribute only applies to pointer arguments}} +void noescapeFunc5(__attribute__((noescape)) T); template void noescapeFunc6(__attribute__((noescape)) const T &); template @@ -144,7 +144,7 @@ -(void) m1:(int*) p { struct S6 { S6(); - S6(const S6 &) = delete; // expected-note 12 {{'S6' has been explicitly marked deleted here}} + S6(const S6 &) = delete; // expected-note 11 {{'S6' has been explicitly marked deleted here}} int f; }; @@ -161,7 +161,7 @@ void test1(C0 *c0) { __block S6 b6; // expected-error {{call to deleted constructor of 'S6'}} __block S6 b7; // expected-error {{call to deleted constructor of 'S6'}} __block S6 b8; // expected-error {{call to deleted constructor of 'S6'}} - __block S6 b9; // expected-error {{call to deleted constructor of 'S6'}} + __block S6 b9; __block S6 b10; // expected-error {{call to deleted constructor of 'S6'}} __block S6 b11; // expected-error {{call to deleted constructor of 'S6'}} __block S6 b12; @@ -199,7 +199,6 @@ void test1(C0 *c0) { (void)b8; }); - // FIXME: clang shouldn't reject this. noescapeFunc5(^{ (void)b9; });