]> granicus.if.org Git - clang/commitdiff
Refactor ActOnDeclarationNameExpr into a "parsing action" part and a
authorDouglas Gregor <dgregor@apple.com>
Tue, 30 Jun 2009 15:47:41 +0000 (15:47 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 30 Jun 2009 15:47:41 +0000 (15:47 +0000)
"semantic analysis" part. Use the "semantic analysis" part when
performing template instantiation on a DeclRefExpr, rather than an ad
hoc list of rules to construct DeclRefExprs from the instantiation.

A test case for this change will come in with a large commit, which
illustrates what I was actually trying to work on.

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

lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/SemaTemplateInstantiateExpr.cpp

index 0fa66c4937d92564d222c3842a95c1be7342f65a..42c43291a9614145477c72126e60714ef563caad 100644 (file)
@@ -1401,7 +1401,11 @@ public:
                                             bool HasTrailingLParen,
                                             const CXXScopeSpec *SS,
                                             bool isAddressOfOperand = false);
-
+  OwningExprResult BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
+                                            bool HasTrailingLParen,
+                                            const CXXScopeSpec *SS, 
+                                            bool isAddressOfOperand);
+    
   virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
                                                tok::TokenKind Kind);
   virtual OwningExprResult ActOnNumericConstant(const Token &);
index 1df3d4f722f6ec91e706ed286a5e3d40b7c4c30d..1c5b76075e0488a56afd5d08c53f279e80654b4c 100644 (file)
@@ -970,7 +970,64 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
         return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name);
     }
   }
+  
+  if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+    // Warn about constructs like:
+    //   if (void *X = foo()) { ... } else { X }.
+    // In the else block, the pointer is always false.
+    
+    // FIXME: In a template instantiation, we don't have scope
+    // information to check this property.
+    if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
+      Scope *CheckS = S;
+      while (CheckS) {
+        if (CheckS->isWithinElse() && 
+            CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
+          if (Var->getType()->isBooleanType())
+            ExprError(Diag(Loc, diag::warn_value_always_false)
+                      << Var->getDeclName());
+          else
+            ExprError(Diag(Loc, diag::warn_value_always_zero)
+                      << Var->getDeclName());
+          break;
+        }
+        
+        // Move up one more control parent to check again.
+        CheckS = CheckS->getControlParent();
+        if (CheckS)
+          CheckS = CheckS->getParent();
+      }
+    }
+  } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) {
+    if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) {
+      // C99 DR 316 says that, if a function type comes from a
+      // function definition (without a prototype), that type is only
+      // used for checking compatibility. Therefore, when referencing
+      // the function, we pretend that we don't have the full function
+      // type.
+      if (DiagnoseUseOfDecl(Func, Loc))
+        return ExprError();
 
+      QualType T = Func->getType();
+      QualType NoProtoType = T;
+      if (const FunctionProtoType *Proto = T->getAsFunctionProtoType())
+        NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
+      return BuildDeclRefExpr(Func, NoProtoType, Loc, false, false, SS);
+    }
+  }
+  
+  return BuildDeclarationNameExpr(Loc, D, HasTrailingLParen, SS, isAddressOfOperand);
+}
+
+/// \brief Complete semantic analysis for a reference to the given declaration.
+Sema::OwningExprResult
+Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
+                               bool HasTrailingLParen,
+                               const CXXScopeSpec *SS, 
+                               bool isAddressOfOperand) {
+  assert(D && "Cannot refer to a NULL declaration");
+  DeclarationName Name = D->getDeclName();
+  
   // If this is an expression of the form &Class::member, don't build an
   // implicit member ref, because we want a pointer to the member in general,
   // not any specific instance's member.
@@ -1094,51 +1151,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
   // this check when we're going to perform argument-dependent lookup
   // on this function name, because this might not be the function
   // that overload resolution actually selects.
+  bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && 
+             HasTrailingLParen;
   if (!(ADL && isa<FunctionDecl>(VD)) && DiagnoseUseOfDecl(VD, Loc))
     return ExprError();
 
-  if (VarDecl *Var = dyn_cast<VarDecl>(VD)) {
-    // Warn about constructs like:
-    //   if (void *X = foo()) { ... } else { X }.
-    // In the else block, the pointer is always false.
-
-    // FIXME: In a template instantiation, we don't have scope
-    // information to check this property.
-    if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
-      Scope *CheckS = S;
-      while (CheckS) {
-        if (CheckS->isWithinElse() && 
-            CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
-          if (Var->getType()->isBooleanType())
-            ExprError(Diag(Loc, diag::warn_value_always_false)
-              << Var->getDeclName());
-          else
-            ExprError(Diag(Loc, diag::warn_value_always_zero)
-              << Var->getDeclName());
-          break;
-        }
-
-        // Move up one more control parent to check again.
-        CheckS = CheckS->getControlParent();
-        if (CheckS)
-          CheckS = CheckS->getParent();
-      }
-    }
-  } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(VD)) {
-    if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) {
-      // C99 DR 316 says that, if a function type comes from a
-      // function definition (without a prototype), that type is only
-      // used for checking compatibility. Therefore, when referencing
-      // the function, we pretend that we don't have the full function
-      // type.
-      QualType T = Func->getType();
-      QualType NoProtoType = T;
-      if (const FunctionProtoType *Proto = T->getAsFunctionProtoType())
-        NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
-      return BuildDeclRefExpr(VD, NoProtoType, Loc, false, false, SS);
-    }
-  }
-
   // Only create DeclRefExpr's for valid Decl's.
   if (VD->isInvalidDecl())
     return ExprError();
index 97a160e7155097dfe4fa2593046a143338db3422..7053bba8ede669286b345db7a7ecba8c3e9c3f0e 100644 (file)
@@ -865,6 +865,6 @@ void Sema::PerformPendingImplicitInstantiations() {
       if (!Function->getBody())
         InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function);
     
-    // FIXME: instantiation static member variables
+    // FIXME: instantiate static member variables
   }
 }
index e1702b52a66318e7388cf47b80fb18dc3949af3d..719a9eda47179faa59779488c44fdb0a58939dd3 100644 (file)
@@ -156,18 +156,15 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
                                                            false, false));
   }
 
-  ValueDecl *NewD 
-    = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateCurrentDeclRef(D));
-  if (!NewD)
+  NamedDecl *InstD = SemaRef.InstantiateCurrentDeclRef(D);
+  if (!InstD)
     return SemaRef.ExprError();
 
-  // FIXME: Build QualifiedDeclRefExpr?
-  QualType T = NewD->getType();
-  return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(NewD,
-                                                      T.getNonReferenceType(),
-                                                           E->getLocation(),
-                                                        T->isDependentType(),
-                                                        T->isDependentType()));
+  // FIXME: nested-name-specifier for QualifiedDeclRefExpr
+  return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, 
+                                          /*FIXME:*/false,
+                                          /*FIXME:*/0, 
+                                          /*FIXME:*/false);
 }
 
 Sema::OwningExprResult