summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp84
-rw-r--r--clang/lib/Sema/SemaDecl.cpp4
-rw-r--r--clang/lib/Sema/SemaLookup.cpp2
3 files changed, 33 insertions, 57 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 098298f0c59..7485b12614d 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1451,32 +1451,6 @@ void NamedDecl::getNameForDiagnostic(raw_ostream &OS,
printName(OS);
}
-static bool isKindReplaceableBy(Decl::Kind OldK, Decl::Kind NewK) {
- // For method declarations, we never replace.
- if (ObjCMethodDecl::classofKind(NewK))
- return false;
-
- if (OldK == NewK)
- return true;
-
- // A compatibility alias for a class can be replaced by an interface.
- if (ObjCCompatibleAliasDecl::classofKind(OldK) &&
- ObjCInterfaceDecl::classofKind(NewK))
- return true;
-
- // A typedef-declaration, alias-declaration, or Objective-C class declaration
- // can replace another declaration of the same type. Semantic analysis checks
- // that we have matching types.
- if ((TypedefNameDecl::classofKind(OldK) ||
- ObjCInterfaceDecl::classofKind(OldK)) &&
- (TypedefNameDecl::classofKind(NewK) ||
- ObjCInterfaceDecl::classofKind(NewK)))
- return true;
-
- // Otherwise, a kind mismatch implies that the declaration is not replaced.
- return false;
-}
-
template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) {
return true;
}
@@ -1500,9 +1474,19 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
if (OldD->isFromASTFile() && isFromASTFile())
return false;
- if (!isKindReplaceableBy(OldD->getKind(), getKind()))
+ // A kind mismatch implies that the declaration is not replaced.
+ if (OldD->getKind() != getKind())
return false;
+ // For method declarations, we never replace. (Why?)
+ if (isa<ObjCMethodDecl>(this))
+ return false;
+
+ // For parameters, pick the newer one. This is either an error or (in
+ // Objective-C) permitted as an extension.
+ if (isa<ParmVarDecl>(this))
+ return true;
+
// Inline namespaces can give us two declarations with the same
// name and kind in the same scope but different contexts; we should
// keep both declarations in this case.
@@ -1510,28 +1494,8 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
OldD->getDeclContext()->getRedeclContext()))
return false;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
- // For function declarations, we keep track of redeclarations.
- // FIXME: This returns false for functions that should in fact be replaced.
- // Instead, perform some kind of type check?
- if (FD->getPreviousDecl() != OldD)
- return false;
-
- // For function templates, the underlying function declarations are linked.
- if (const FunctionTemplateDecl *FunctionTemplate =
- dyn_cast<FunctionTemplateDecl>(this))
- return FunctionTemplate->getTemplatedDecl()->declarationReplaces(
- cast<FunctionTemplateDecl>(OldD)->getTemplatedDecl());
-
- // Using shadow declarations can be overloaded on their target declarations
- // if they introduce functions.
- // FIXME: If our target replaces the old target, can we replace the old
- // shadow declaration?
- if (auto *USD = dyn_cast<UsingShadowDecl>(this))
- if (USD->getTargetDecl() != cast<UsingShadowDecl>(OldD)->getTargetDecl())
- return false;
-
- // Using declarations can be overloaded if they introduce functions.
+ // Using declarations can be replaced if they import the same name from the
+ // same context.
if (auto *UD = dyn_cast<UsingDecl>(this)) {
ASTContext &Context = getASTContext();
return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
@@ -1546,13 +1510,20 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
}
// UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
- // We want to keep it, unless it nominates same namespace.
+ // They can be replaced if they nominate the same namespace.
+ // FIXME: Is this true even if they have different module visibility?
if (auto *UD = dyn_cast<UsingDirectiveDecl>(this))
return UD->getNominatedNamespace()->getOriginalNamespace() ==
cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
->getOriginalNamespace();
- if (!IsKnownNewer && isRedeclarable(getKind())) {
+ if (isRedeclarable(getKind())) {
+ if (getCanonicalDecl() != OldD->getCanonicalDecl())
+ return false;
+
+ if (IsKnownNewer)
+ return true;
+
// Check whether this is actually newer than OldD. We want to keep the
// newer declaration. This loop will usually only iterate once, because
// OldD is usually the previous declaration.
@@ -1567,11 +1538,16 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
if (D->isCanonicalDecl())
return false;
}
+
+ // It's a newer declaration of the same kind of declaration in the same
+ // scope: we want this decl instead of the existing one.
+ return true;
}
- // It's a newer declaration of the same kind of declaration in the same scope,
- // and not an overload: we want this decl instead of the existing one.
- return true;
+ // In all other cases, we need to keep both declarations in case they have
+ // different visibility. Any attempt to use the name will result in an
+ // ambiguity if more than one is visible.
+ return false;
}
bool NamedDecl::hasLinkage() const {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 622ff1ebbce..e188094f90a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3352,7 +3352,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
- return;
+ return New->setInvalidDecl();
// C++ [class.mem]p1:
// A member shall not be declared twice in the member-specification [...]
@@ -8220,7 +8220,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// there's no more work to do here; we'll just add the new
// function to the scope.
if (!AllowOverloadingOfFunction(Previous, Context)) {
- NamedDecl *Candidate = Previous.getFoundDecl();
+ NamedDecl *Candidate = Previous.getRepresentativeDecl();
if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) {
Redeclaration = true;
OldDecl = Candidate;
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 6fbe0da8c90..0ba34ea8ef2 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -474,7 +474,7 @@ void LookupResult::resolveKind() {
D = cast<NamedDecl>(D->getCanonicalDecl());
// Ignore an invalid declaration unless it's the only one left.
- if (D->isInvalidDecl() && I < N-1) {
+ if (D->isInvalidDecl() && !(I == 0 && N == 1)) {
Decls[I] = Decls[--N];
continue;
}
OpenPOWER on IntegriCloud