]> granicus.if.org Git - clang/commitdiff
Basic support for member exprs where the base expr type is dependent.
authorAnders Carlsson <andersca@mac.com>
Fri, 15 May 2009 23:10:19 +0000 (23:10 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 15 May 2009 23:10:19 +0000 (23:10 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71907 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/AST/Expr.cpp
lib/Sema/SemaExpr.cpp
test/SemaTemplate/instantiate-function-1.cpp

index 441aae2c73051821bc3a64c0b8befc708712b5de..eceb93e64a9b0027ff43a748b087a3cb6ab8210a 100644 (file)
@@ -1040,7 +1040,8 @@ class MemberExpr : public Expr {
 public:
   MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l,
              QualType ty) 
-    : Expr(MemberExprClass, ty),
+    : Expr(MemberExprClass, ty, 
+           base->isTypeDependent(), base->isValueDependent()),
       Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {}
 
   /// \brief Build an empty member reference expression.
index 0d38dd2cd12d867c00aa02fd4cfb915566eecc46..9a860033dfd00e1c92a2ebdddaa92d13f5363ab8 100644 (file)
@@ -417,6 +417,11 @@ Stmt *BlockExpr::getBody() {
 /// warning.
 bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
                                   SourceRange &R2) const {
+  // Don't warn if the expr is type dependent. The type could end up
+  // instantiating to void.
+  if (isTypeDependent())
+    return false;
+  
   switch (getStmtClass()) {
   default:
     Loc = getExprLoc();
index 0d72a7534e0f6129cf1761f6331839053ebc5955..41c868e00558ce45eecc41c8c465b393024f7336 100644 (file)
@@ -2024,7 +2024,10 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
   // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
   // must have pointer type, and the accessed type is the pointee.
   if (OpKind == tok::arrow) {
-    if (const PointerType *PT = BaseType->getAsPointerType())
+    if (BaseType->isDependentType())
+      return Owned(new (Context) MemberExpr(BaseExpr, true, 0,
+                                            MemberLoc, Context.DependentTy));
+    else if (const PointerType *PT = BaseType->getAsPointerType())
       BaseType = PT->getPointeeType();
     else if (getLangOptions().CPlusPlus && BaseType->isRecordType())
       return Owned(BuildOverloadedArrowExpr(S, BaseExpr, OpLoc,
@@ -2033,6 +2036,17 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
       return ExprError(Diag(MemberLoc,
                             diag::err_typecheck_member_reference_arrow)
         << BaseType << BaseExpr->getSourceRange());
+  } else {
+    // We use isTemplateTypeParmType directly here, instead of simply checking
+    // whether BaseType is dependent, because we want to report an error for
+    //
+    // T *t;
+    // t.foo;
+    //
+    //
+    if (BaseType->isTemplateTypeParmType()) 
+      return Owned(new (Context) MemberExpr(BaseExpr, false, 0,
+                                            MemberLoc, Context.DependentTy));
   }
 
   // Handle field access to simple records.  This also handles access to fields
index dc4859805051a39a4944d892296540ab66ff51cc..1dfe9e2da6ac9275857a299c5eb52dd6b9f45d8c 100644 (file)
@@ -125,3 +125,18 @@ template<typename T> struct For0 {
 };
 
 template struct For0<int*>;
+
+template<typename T> struct Member0 {
+  void f(T t) {
+    t;
+    t.f;
+    t->f;
+    
+    T* tp;
+    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
+    tp->f;
+
+    this->f;
+    this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}}
+  }
+};