diff options
-rw-r--r-- | include/clang/AST/Attr.h | 6 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.def | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 27 | ||||
-rw-r--r-- | test/Sema/overloadable.c | 7 |
4 files changed, 25 insertions, 17 deletions
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 328ba5764a..60b84f43c3 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -70,6 +70,10 @@ public: delete Next; } + /// \brief Whether this attribute should be merged to new + /// declarations. + virtual bool isMerged() const { return true; } + Kind getKind() const { return AttrKind; } Attr *getNext() { return Next; } @@ -449,6 +453,8 @@ class OverloadableAttr : public Attr { public: OverloadableAttr() : Attr(Overloadable) { } + virtual bool isMerged() const { return false; } + static bool classof(const Attr *A) { return A->getKind() == Overloadable; } static bool classof(const OverloadableAttr *) { return true; } }; diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index 0eddb39e7d..1024377cd0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -396,7 +396,7 @@ DIAG(err_attribute_iboutlet_non_ivar, ERROR, DIAG(err_attribute_overloadable_not_function, ERROR, "'overloadable' attribute can only be applied to a function") DIAG(err_attribute_overloadable_missing, ERROR, - "overloaded function %0 must have the 'overloadable' attribute") + "%select{overloaded function|redeclaration of}0 %1 must have the 'overloadable' attribute") DIAG(note_attribute_overloadable_prev_overload, NOTE, "previous overload of function is here") diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index de06ca610c..0dbd6d3804 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -446,15 +446,15 @@ static void MergeAttributes(Decl *New, Decl *Old) { Attr *attr = const_cast<Attr*>(Old->getAttrs()), *tmp; while (attr) { - tmp = attr; - attr = attr->getNext(); + tmp = attr; + attr = attr->getNext(); - if (!DeclHasAttr(New, tmp)) { - tmp->setInherited(true); - New->addAttr(tmp); + if (!DeclHasAttr(New, tmp) && tmp->isMerged()) { + tmp->setInherited(true); + New->addAttr(tmp); } else { - tmp->setNext(0); - delete(tmp); + tmp->setNext(0); + delete(tmp); } } @@ -1666,6 +1666,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // there's no more work to do here; we'll just add the new // function to the scope. OverloadedFunctionDecl::function_iterator MatchedDecl; + + if (!getLangOptions().CPlusPlus && + AllowOverloadingOfFunction(PrevDecl, Context)) + OverloadableAttrRequired = true; + if (!AllowOverloadingOfFunction(PrevDecl, Context) || !IsOverload(NewFD, PrevDecl, MatchedDecl)) { Decl *OldDecl = PrevDecl; @@ -1693,12 +1698,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } } - - // If we're in C, this new declaration better have the - // "overloadable" attribute on it. - if (!getLangOptions().CPlusPlus && - PrevDecl->getAttr<OverloadableAttr>()) - OverloadableAttrRequired = true; } if (D.getCXXScopeSpec().isSet() && @@ -1743,7 +1742,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // If a function name is overloadable in C, then every function // with that name must be marked "overloadable". Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) - << NewFD; + << Redeclaration << NewFD; if (PrevDecl) Diag(PrevDecl->getLocation(), diag::note_attribute_overloadable_prev_overload); diff --git a/test/Sema/overloadable.c b/test/Sema/overloadable.c index 5118e40ab0..040b7faf7c 100644 --- a/test/Sema/overloadable.c +++ b/test/Sema/overloadable.c @@ -2,9 +2,10 @@ int var __attribute__((overloadable)); // expected-error{{'overloadable' attribute can only be applied to a function}} -int *f(int) __attribute__((overloadable)); // expected-note{{previous overload of function is here}} +int *f(int) __attribute__((overloadable)); // expected-note 2{{previous overload of function is here}} float *f(float); // expected-error{{overloaded function 'f' must have the 'overloadable' attribute}} -int *f(int); // expected-note{{previous declaration is here}} +int *f(int); // expected-error{{redeclaration of 'f' must have the 'overloadable' attribute}} \ + // expected-note{{previous declaration is here}} double *f(double) __attribute__((overloadable)); // okay, new void test_f(int iv, float fv, double dv) { @@ -35,3 +36,5 @@ void test_struct(struct X x, struct Y y) { } double *f(int) __attribute__((overloadable)); // expected-error{{conflicting types for 'f'}} + + |