]> granicus.if.org Git - clang/commitdiff
PR7837: For qualified id's, make sure the decl context is complete if not
authorEli Friedman <eli.friedman@gmail.com>
Fri, 6 Aug 2010 23:41:47 +0000 (23:41 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Fri, 6 Aug 2010 23:41:47 +0000 (23:41 +0000)
dependent in ActOnIdExpression.  (This issue only shows up with member
operators because an operator is never a type.)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110486 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/SemaTemplate/dependent-class-member-operator.cpp [new file with mode: 0644]

index 46c5a65f75ddbdd7c6fec17e8175f1e47851259e..82a2bb2982c40ef1aec1545b3998094e5fb2ac32 100644 (file)
@@ -699,23 +699,6 @@ static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
   return true;
 }
 
-/// Determines whether we can lookup this id-expression now or whether
-/// we have to wait until template instantiation is complete.
-static bool IsDependentIdExpression(Sema &SemaRef, const CXXScopeSpec &SS) {
-  DeclContext *DC = SemaRef.computeDeclContext(SS, false);
-
-  // If the qualifier scope isn't computable, it's definitely dependent.
-  if (!DC) return true;
-
-  // If the qualifier scope doesn't name a record, we can always look into it.
-  if (!isa<CXXRecordDecl>(DC)) return false;
-
-  // We can't look into record types unless they're fully-formed.
-  if (!IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC))) return true;
-
-  return false;
-}
-
 /// Determines if the given class is provably not derived from all of
 /// the prospective base classes.
 static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
@@ -1100,9 +1083,24 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
   //        names a dependent type.
   // Determine whether this is a member of an unknown specialization;
   // we need to handle these differently.
-  if ((Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
-       Name.getCXXNameType()->isDependentType()) ||
-      (SS.isSet() && IsDependentIdExpression(*this, SS))) {
+  bool DependentID = false;
+  if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+      Name.getCXXNameType()->isDependentType()) {
+    DependentID = true;
+  } else if (SS.isSet()) {
+    DeclContext *DC = computeDeclContext(SS, false);
+    if (DC) {
+      if (RequireCompleteDeclContext(SS, DC))
+        return ExprError();
+      // FIXME: We should be checking whether DC is the current instantiation.
+      if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
+        DependentID = !IsFullyFormedScope(*this, RD);
+    } else {
+      DependentID = true;
+    }
+  }
+
+  if (DependentID) {
     return ActOnDependentIdExpression(SS, Name, NameLoc,
                                       isAddressOfOperand,
                                       TemplateArgs);
diff --git a/test/SemaTemplate/dependent-class-member-operator.cpp b/test/SemaTemplate/dependent-class-member-operator.cpp
new file mode 100644 (file)
index 0000000..d70a60c
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// PR7837
+
+template<class T> struct C1 { void operator()(T); };
+template<class T> struct C2; // expected-note {{template is declared here}}
+template<class T> void foo(T);
+void wrap() {
+  foo(&C1<int>::operator());
+  foo(&C1<int>::operator+); // expected-error {{no member named 'operator+' in 'C1<int>'}}
+  foo(&C2<int>::operator+); // expected-error {{implicit instantiation of undefined template 'C2<int>'}}
+}