]> granicus.if.org Git - clang/commitdiff
Require the object type of a member access expression ("." or "->") to
authorDouglas Gregor <dgregor@apple.com>
Tue, 17 Nov 2009 05:17:33 +0000 (05:17 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 17 Nov 2009 05:17:33 +0000 (05:17 +0000)
be complete.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/class-template-spec.cpp
test/SemaTemplate/member-function-template.cpp

index e1fe4dd4b6005fbced98e3db1b9b7090b03d67fa..fd544827b15e3972ddbd0e79618091c2ed356248 100644 (file)
@@ -401,7 +401,9 @@ def note_ambig_member_ref_scope : Note<
   "lookup from the current scope refers here">;
 def err_qualified_member_nonclass : Error<
   "qualified member access refers to a member in %0">;
-
+def err_incomplete_member_access : Error<
+  "member access into incomplete type %0">;
+  
 // C++ class members
 def err_storageclass_invalid_for_member : Error<
   "storage class specified for a member declaration">;
index fdce0e6c2dc354ed9de0c0f2bf35d291c31efe49..dd3fd2c5c1afa8b06768111944fef4f03d161365 100644 (file)
@@ -2141,12 +2141,19 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
     return move(Base);
   }
 
+  // The object type must be complete (or dependent).
+  if (!BaseType->isDependentType() &&
+      RequireCompleteType(OpLoc, BaseType, 
+                          PDiag(diag::err_incomplete_member_access)))
+    return ExprError();
+  
   // C++ [basic.lookup.classref]p2:
   //   If the id-expression in a class member access (5.2.5) is an
-  //   unqualified-id, and the type of the object expression is of a class
+  //   unqualified-id, and the type of the object expression is of a class
   //   type C (or of pointer to a class type C), the unqualified-id is looked
   //   up in the scope of class C. [...]
   ObjectType = BaseType.getAsOpaquePtr();
+  
   return move(Base);
 }
 
index 317d1339540e1e1d3334318d84d56fc12cb03861..a799ddb24bf2f6048bb14af6a8298570ccc3a378 100644 (file)
@@ -130,12 +130,17 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
     QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
     LookupCtx = computeDeclContext(ObjectType);
     isDependent = ObjectType->isDependentType();
+    assert((isDependent || !ObjectType->isIncompleteType()) && 
+           "Caller should have completed object type");
   } else if (SS.isSet()) {
     // This nested-name-specifier occurs after another nested-name-specifier,
     // so long into the context associated with the prior nested-name-specifier.
-
     LookupCtx = computeDeclContext(SS, EnteringContext);
     isDependent = isDependentScopeSpecifier(SS);
+    
+    // The declaration context must be complete.
+    if (LookupCtx && RequireCompleteDeclContext(SS))
+      return TNK_Non_template;
   }
 
   LookupResult Found(*this, TName, SourceLocation(), LookupOrdinaryName);
@@ -145,11 +150,6 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
     // 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.
-
-    // The declaration context must be complete.
-    if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS))
-      return TNK_Non_template;
-
     LookupQualifiedName(Found, LookupCtx);
 
     if (ObjectTypePtr && Found.empty()) {
index 5bc9a6cd67daa14c3d9266d96280f07fd41b7300..2808404b1d99f652dc778c43e15849500fd9f763 100644 (file)
@@ -19,7 +19,7 @@ int test_specs(A<float, float> *a1, A<float, int> *a2) {
 int test_incomplete_specs(A<double, double> *a1, 
                           A<double> *a2)
 {
-  (void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
+  (void)a1->x; // expected-error{{member access into incomplete type}}
   (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
 }
 
index 756b510e97fd90bea290cad3b6ee14e8646adb9d..1d46d31e35d348606dec0401eaf9e33fed684900 100644 (file)
@@ -60,3 +60,16 @@ struct Functor {
 void test_Functor(Functor f) {
   f(1);
 }
+
+// Instantiation on ->
+template<typename T>
+struct X1 {
+  template<typename U> U& get();
+};
+
+template<typename T> struct X2; // expected-note{{here}}
+
+void test_incomplete_access(X1<int> *x1, X2<int> *x2) {
+  float &fr = x1->get<float>();
+  (void)x2->get<float>(); // expected-error{{implicit instantiation of undefined template}}
+}