diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f736ab55fdd0..5665cf0c87b0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -818,6 +818,9 @@ def err_attribute_argument_not_int : Error< def err_attribute_argument_outof_range : Error< "init_priority attribute requires integer constant between " "101 and 65535 inclusive">; +def err_init_priority_object_attr : Error< + "can only use ‘init_priority’ attribute on file-scope definitions " + "of objects of class type">; def err_attribute_argument_n_not_int : Error< "'%0' attribute requires parameter %1 to be an integer constant">; def err_attribute_argument_n_not_string : Error< diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b54bc1ed9f52..c5eb048577a4 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1189,12 +1189,27 @@ static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr, return; } + if (!isa(d) || S.getCurFunctionOrMethodDecl()) { + S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); + Attr.setInvalid(); + return; + } + QualType T = dyn_cast(d)->getType(); + if (S.Context.getAsArrayType(T)) + T = S.Context.getBaseElementType(T); + if (!T->getAs()) { + S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); + Attr.setInvalid(); + return; + } + if (Attr.getNumArgs() != 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; Attr.setInvalid(); return; } Expr *priorityExpr = static_cast(Attr.getArg(0)); + llvm::APSInt priority(32); if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { diff --git a/clang/test/SemaCXX/init-priority-attr.cpp b/clang/test/SemaCXX/init-priority-attr.cpp new file mode 100644 index 000000000000..6ea263d1e59d --- /dev/null +++ b/clang/test/SemaCXX/init-priority-attr.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class Two { +private: + int i, j, k; +public: + static int count; + Two( int ii, int jj ) { i = ii; j = jj; k = count++; }; + Two( void ) { i = 0; j = 0; k = count++; }; + int eye( void ) { return i; }; + int jay( void ) { return j; }; + int kay( void ) { return k; }; +}; + +extern Two foo; +extern Two goo; +extern Two coo[]; +extern Two koo[]; + +Two foo __attribute__((init_priority(101))) ( 5, 6 ); + +Two goo __attribute__((init_priority(2,3))) ( 5, 6 ); // expected-error {{attribute requires 1 argument(s)}} + +Two coo[2] __attribute__((init_priority(3))); // expected-error {{init_priority attribute requires integer constant between 101 and 65535 inclusive}} + +Two koo[4] __attribute__((init_priority(1.13))); // expected-error {{'init_priority' attribute requires integer constant}} + + +Two func() __attribute__((init_priority(1001))); // expected-error {{can only use ‘init_priority’ attribute on file-scope definitions of objects of class type}} + +int i __attribute__((init_priority(1001))); // expected-error {{can only use ‘init_priority’ attribute on file-scope definitions of objects of class type}} + +int main() { + Two foo __attribute__((init_priority(1001))); // expected-error {{can only use ‘init_priority’ attribute on file-scope definitions of objects of class type}} +} +