diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-13 00:26:38 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-13 00:26:38 +0000 |
commit | ae17094c001972a5949944a0a77ef6adf2a92c8f (patch) | |
tree | 528d8d092ed0dca534946b1eee43235ddadda8d6 /lib/Sema/SemaDecl.cpp | |
parent | 5f2bfd4811996abb783aa6c7254c56baa6930e8c (diff) |
Tighten checking of the "overloadable" attribute. If any function by a
given name in a given scope is marked as "overloadable", every
function declaration and definition with that same name and in that
same scope needs to have the "overloadable" attribute. Essentially,
the "overloadable" attribute is not part of attribute merging, so it
must be specified even for redeclarations. This keeps users from
trying to be too sneaky for their own good:
double sin(double) __attribute__((overloadable)); // too sneaky
#include <math.h>
Previously, this would have made "sin" overloadable, and therefore
given it a mangled name. Now, we get an error inside math.h when we
see a (re)declaration of "sin" that doesn't have the "overloadable"
attribute.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64414 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 27 |
1 files changed, 13 insertions, 14 deletions
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); |