aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Attr.h6
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.def2
-rw-r--r--lib/Sema/SemaDecl.cpp27
-rw-r--r--test/Sema/overloadable.c7
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'}}
+
+