Skip to content

Commit d0d2ee0

Browse files
committed
When performing qualified name lookup into the current instantiation,
do not look into base classes if there are any dependent base classes. Instead, note in the lookup result that we couldn't look into any dependent bases. Use that new result kind to detect when this case occurs, so that we can fall back to treating the type/value/etc. as a member of an unknown specialization. Fixes an issue where we were resolving lookup at template definition time and then missing an ambiguity at template instantiation time. llvm-svn: 93497
1 parent cefa7ad commit d0d2ee0

File tree

6 files changed

+73
-33
lines changed

6 files changed

+73
-33
lines changed

clang/lib/Sema/Lookup.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ class LookupResult {
3232
/// @brief No entity found met the criteria.
3333
NotFound = 0,
3434

35+
/// @brief No entity found met the criteria within the current
36+
/// instantiation,, but there were dependent base classes of the
37+
/// current instantiation that could not be searched.
38+
NotFoundInCurrentInstantiation,
39+
3540
/// @brief Name lookup found a single declaration that met the
3641
/// criteria. getFoundDecl() will return this declaration.
3742
Found,
@@ -268,6 +273,19 @@ class LookupResult {
268273
Decls.set_size(N);
269274
}
270275

276+
/// \brief Determine whether no result was found because we could not
277+
/// search into dependent base classes of the current instantiation.
278+
bool wasNotFoundInCurrentInstantiation() const {
279+
return ResultKind == NotFoundInCurrentInstantiation;
280+
}
281+
282+
/// \brief Note that while no result was found in the current instantiation,
283+
/// there were dependent base classes that could not be searched.
284+
void setNotFoundInCurrentInstantiation() {
285+
assert(ResultKind == NotFound && Decls.empty());
286+
ResultKind = NotFoundInCurrentInstantiation;
287+
}
288+
271289
/// \brief Resolves the result kind of the lookup, possibly hiding
272290
/// decls.
273291
///
@@ -278,9 +296,10 @@ class LookupResult {
278296
/// \brief Re-resolves the result kind of the lookup after a set of
279297
/// removals has been performed.
280298
void resolveKindAfterFilter() {
281-
if (Decls.empty())
282-
ResultKind = NotFound;
283-
else {
299+
if (Decls.empty()) {
300+
if (ResultKind != NotFoundInCurrentInstantiation)
301+
ResultKind = NotFound;
302+
} else {
284303
ResultKind = Found;
285304
resolveKind();
286305
}

clang/lib/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1212,7 +1212,8 @@ class Sema : public Action {
12121212
= NotForRedeclaration);
12131213
bool LookupName(LookupResult &R, Scope *S,
12141214
bool AllowBuiltinCreation = false);
1215-
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx);
1215+
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
1216+
bool InUnqualifiedLookup = false);
12161217
bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
12171218
bool AllowBuiltinCreation = false,
12181219
bool EnteringContext = false);

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
138138
NamedDecl *IIDecl = 0;
139139
switch (Result.getResultKind()) {
140140
case LookupResult::NotFound:
141+
case LookupResult::NotFoundInCurrentInstantiation:
141142
case LookupResult::FoundOverloaded:
142143
case LookupResult::FoundUnresolvedValue:
143144
return 0;
@@ -4791,7 +4792,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
47914792
// and that current instantiation has any dependent base
47924793
// classes, we might find something at instantiation time: treat
47934794
// this as a dependent elaborated-type-specifier.
4794-
if (isCurrentInstantiationWithDependentBases(SS)) {
4795+
if (Previous.wasNotFoundInCurrentInstantiation()) {
47954796
IsDependent = true;
47964797
return DeclPtrTy();
47974798
}

clang/lib/Sema/SemaLookup.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
623623
// example, inside a class without any base classes, we never need to
624624
// perform qualified lookup because all of the members are on top of the
625625
// identifier chain.
626-
if (LookupQualifiedName(R, Ctx))
626+
if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true))
627627
return true;
628628
}
629629
}
@@ -927,37 +927,30 @@ static bool LookupQualifiedNameInUsingDirectives(LookupResult &R,
927927
return Found;
928928
}
929929

930-
/// @brief Perform qualified name lookup into a given context.
930+
/// \brief Perform qualified name lookup into a given context.
931931
///
932932
/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
933933
/// names when the context of those names is explicit specified, e.g.,
934-
/// "std::vector" or "x->member".
934+
/// "std::vector" or "x->member", or as part of unqualified name lookup.
935935
///
936936
/// Different lookup criteria can find different names. For example, a
937937
/// particular scope can have both a struct and a function of the same
938938
/// name, and each can be found by certain lookup criteria. For more
939939
/// information about lookup criteria, see the documentation for the
940940
/// class LookupCriteria.
941941
///
942-
/// @param LookupCtx The context in which qualified name lookup will
942+
/// \param R captures both the lookup criteria and any lookup results found.
943+
///
944+
/// \param LookupCtx The context in which qualified name lookup will
943945
/// search. If the lookup criteria permits, name lookup may also search
944946
/// in the parent contexts or (for C++ classes) base classes.
945947
///
946-
/// @param Name The name of the entity that we are searching for.
947-
///
948-
/// @param Criteria The criteria that this routine will use to
949-
/// determine which names are visible and which names will be
950-
/// found. Note that name lookup will find a name that is visible by
951-
/// the given criteria, but the entity itself may not be semantically
952-
/// correct or even the kind of entity expected based on the
953-
/// lookup. For example, searching for a nested-name-specifier name
954-
/// might result in an EnumDecl, which is visible but is not permitted
955-
/// as a nested-name-specifier in C++03.
948+
/// \param InUnqualifiedLookup true if this is qualified name lookup that
949+
/// occurs as part of unqualified name lookup.
956950
///
957-
/// @returns The result of name lookup, which includes zero or more
958-
/// declarations and possibly additional information used to diagnose
959-
/// ambiguities.
960-
bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) {
951+
/// \returns true if lookup succeeded, false if it failed.
952+
bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
953+
bool InUnqualifiedLookup) {
961954
assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
962955

963956
if (!R.getLookupName())
@@ -995,11 +988,22 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) {
995988

996989
// If this isn't a C++ class, we aren't allowed to look into base
997990
// classes, we're done.
998-
if (!isa<CXXRecordDecl>(LookupCtx))
991+
CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
992+
if (!LookupRec)
999993
return false;
1000994

995+
// If we're performing qualified name lookup into a dependent class,
996+
// then we are actually looking into a current instantiation. If we have any
997+
// dependent base classes, then we either have to delay lookup until
998+
// template instantiation time (at which point all bases will be available)
999+
// or we have to fail.
1000+
if (!InUnqualifiedLookup && LookupRec->isDependentContext() &&
1001+
LookupRec->hasAnyDependentBases()) {
1002+
R.setNotFoundInCurrentInstantiation();
1003+
return false;
1004+
}
1005+
10011006
// Perform lookup into our base classes.
1002-
CXXRecordDecl *LookupRec = cast<CXXRecordDecl>(LookupCtx);
10031007
CXXBasePaths Paths;
10041008
Paths.setOrigin(LookupRec);
10051009

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4769,16 +4769,12 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II,
47694769
Decl *Referenced = 0;
47704770
switch (Result.getResultKind()) {
47714771
case LookupResult::NotFound:
4772-
if (CurrentInstantiation && CurrentInstantiation->hasAnyDependentBases()) {
4773-
// We performed a lookup in the current instantiation and didn't
4774-
// find anything. However, this current instantiation has
4775-
// dependent bases, so we might be able to find something at
4776-
// instantiation time: just build a TypenameType and move on.
4777-
return Context.getTypenameType(NNS, &II);
4778-
}
4779-
47804772
DiagID = diag::err_typename_nested_not_found;
47814773
break;
4774+
4775+
case LookupResult::NotFoundInCurrentInstantiation:
4776+
// Okay, it's a member of an unknown instantiation.
4777+
return Context.getTypenameType(NNS, &II);
47824778

47834779
case LookupResult::Found:
47844780
if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {

clang/test/SemaTemplate/dependent-base-classes.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,22 @@ namespace PR6031 {
6363
}
6464
};
6565
}
66+
67+
namespace Ambig {
68+
template<typename T>
69+
struct Base1 {
70+
typedef int type; // expected-note{{member found by ambiguous name lookup}}
71+
};
72+
73+
struct Base2 {
74+
typedef float type; // expected-note{{member found by ambiguous name lookup}}
75+
};
76+
77+
template<typename T>
78+
struct Derived : Base1<T>, Base2 {
79+
typedef typename Derived::type type; // expected-error{{member 'type' found in multiple base classes of different types}}
80+
type *foo(float *fp) { return fp; }
81+
};
82+
83+
Derived<int> di; // expected-note{{instantiation of}}
84+
}

0 commit comments

Comments
 (0)