[cfe-commits] r152520 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
Douglas Gregor
dgregor at apple.com
Sat Mar 10 15:52:41 PST 2012
Author: dgregor
Date: Sat Mar 10 17:52:41 2012
New Revision: 152520
URL: http://llvm.org/viewvc/llvm-project?rev=152520&view=rev
Log:
When determining whether an identifier followed by a '<' in a member
access expression is the start of a template-id, ignore function
templates found in the context of the entire postfix-expression. Fixes
PR11856.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=152520&r1=152519&r2=152520&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Mar 10 17:52:41 2012
@@ -4131,8 +4131,10 @@
//===--------------------------------------------------------------------===//
// C++ Templates [C++ 14]
//
- void FilterAcceptableTemplateNames(LookupResult &R);
- bool hasAnyAcceptableTemplateNames(LookupResult &R);
+ void FilterAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates = true);
+ bool hasAnyAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates = true);
void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
QualType ObjectType, bool EnteringContext,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=152520&r1=152519&r2=152520&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat Mar 10 17:52:41 2012
@@ -44,11 +44,16 @@
/// of a template and, if so, return that template declaration. Otherwise,
/// returns NULL.
static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
- NamedDecl *Orig) {
+ NamedDecl *Orig,
+ bool AllowFunctionTemplates) {
NamedDecl *D = Orig->getUnderlyingDecl();
- if (isa<TemplateDecl>(D))
+ if (isa<TemplateDecl>(D)) {
+ if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D))
+ return 0;
+
return Orig;
+ }
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
// C++ [temp.local]p1:
@@ -78,13 +83,15 @@
return 0;
}
-void Sema::FilterAcceptableTemplateNames(LookupResult &R) {
+void Sema::FilterAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates) {
// The set of class templates we've already seen.
llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
LookupResult::Filter filter = R.makeFilter();
while (filter.hasNext()) {
NamedDecl *Orig = filter.next();
- NamedDecl *Repl = isAcceptableTemplateName(Context, Orig);
+ NamedDecl *Repl = isAcceptableTemplateName(Context, Orig,
+ AllowFunctionTemplates);
if (!Repl)
filter.erase();
else if (Repl != Orig) {
@@ -114,9 +121,10 @@
filter.done();
}
-bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) {
+bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates) {
for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)
- if (isAcceptableTemplateName(Context, *I))
+ if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates))
return true;
return false;
@@ -268,13 +276,13 @@
}
bool ObjectTypeSearchedInScope = false;
+ bool AllowFunctionTemplatesInLookup = true;
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
// computed, which is either the type of the base of a member access
// expression or the declaration context associated with a prior
// nested-name-specifier.
LookupQualifiedName(Found, LookupCtx);
-
if (!ObjectType.isNull() && Found.empty()) {
// C++ [basic.lookup.classref]p1:
// In a class member access expression (5.2.5), if the . or -> token is
@@ -287,6 +295,7 @@
// or function template.
if (S) LookupName(Found, S);
ObjectTypeSearchedInScope = true;
+ AllowFunctionTemplatesInLookup = false;
}
} else if (isDependent && (!S || ObjectType.isNull())) {
// We cannot look into a dependent object type or nested nme
@@ -296,6 +305,9 @@
} else {
// Perform unqualified name lookup in the current scope.
LookupName(Found, S);
+
+ if (!ObjectType.isNull())
+ AllowFunctionTemplatesInLookup = false;
}
if (Found.empty() && !isDependent) {
@@ -335,7 +347,7 @@
}
}
- FilterAcceptableTemplateNames(Found);
+ FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup);
if (Found.empty()) {
if (isDependent)
MemberOfUnknownSpecialization = true;
@@ -351,7 +363,7 @@
LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
LookupOrdinaryName);
LookupName(FoundOuter, S);
- FilterAcceptableTemplateNames(FoundOuter);
+ FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false);
if (FoundOuter.empty()) {
// - if the name is not found, the name found in the class of the
Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp?rev=152520&r1=152519&r2=152520&view=diff
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp (original)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp Sat Mar 10 17:52:41 2012
@@ -62,3 +62,28 @@
}
};
}
+
+namespace PR11856 {
+ template<typename T> T end(T);
+
+ template <typename T>
+ void Foo() {
+ T it1;
+ if (it1->end < it1->end) {
+ }
+ }
+
+ template<typename T> T *end(T*);
+
+ class X { };
+ template <typename T>
+ void Foo2() {
+ T it1;
+ if (it1->end < it1->end) {
+ }
+
+ X *x;
+ if (x->end < 7) { // expected-error{{no member named 'end' in 'PR11856::X'}}
+ }
+ }
+}
More information about the cfe-commits
mailing list