[cfe-commits] r125150 - in /cfe/trunk: include/clang/AST/DeclTemplate.h include/clang/AST/RecursiveASTVisitor.h include/clang/Basic/DeclNodes.td lib/AST/DeclTemplate.cpp lib/Sema/SemaExpr.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp

John McCall rjmccall at apple.com
Tue Feb 8 17:13:10 PST 2011


Author: rjmccall
Date: Tue Feb  8 19:13:10 2011
New Revision: 125150

URL: http://llvm.org/viewvc/llvm-project?rev=125150&view=rev
Log:
NonTypeTemplateParmDecl is just a DeclaratorDecl, not a VarDecl.

Also, reorganize and make very explicit the logic for determining
the value kind and type of a referenced declaration.


Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DeclNodes.td
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Tue Feb  8 19:13:10 2011
@@ -985,7 +985,7 @@
 /// template<int Size> class array { };
 /// @endcode
 class NonTypeTemplateParmDecl
-  : public VarDecl, protected TemplateParmPosition {
+  : public DeclaratorDecl, protected TemplateParmPosition {
   /// \brief The default template argument, if any, and whether or not
   /// it was inherited.
   llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited;
@@ -1007,7 +1007,7 @@
   NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
                           unsigned P, IdentifierInfo *Id, QualType T,
                           bool ParameterPack, TypeSourceInfo *TInfo)
-    : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
+    : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo),
       TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
       ParameterPack(ParameterPack), ExpandedParameterPack(false),
       NumExpandedTypes(0)
@@ -1040,6 +1040,9 @@
   using TemplateParmPosition::setPosition;
   using TemplateParmPosition::getIndex;
 
+  SourceLocation getInnerLocStart() const;
+  SourceRange getSourceRange() const;
+
   /// \brief Determine whether this template parameter has a default
   /// argument.
   bool hasDefaultArgument() const {

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Feb  8 19:13:10 2011
@@ -1538,7 +1538,7 @@
 
 DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
     // A non-type template parameter, e.g. "S" in template<int S> class Foo ...
-    TRY_TO(TraverseVarHelper(D));
+    TRY_TO(TraverseDeclaratorHelper(D));
     TRY_TO(TraverseStmt(D->getDefaultArgument()));
   })
 

Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
+++ cfe/trunk/include/clang/Basic/DeclNodes.td Tue Feb  8 19:13:10 2011
@@ -42,7 +42,7 @@
       def Var : DDecl<Declarator>;
         def ImplicitParam : DDecl<Var>;
         def ParmVar : DDecl<Var>;
-        def NonTypeTemplateParm : DDecl<Var>;
+      def NonTypeTemplateParm : DDecl<Declarator>;
   def Template : DDecl<Named, 1>;
     def RedeclarableTemplate : DDecl<Template, 1>;
       def FunctionTemplate : DDecl<RedeclarableTemplate>;

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Tue Feb  8 19:13:10 2011
@@ -408,7 +408,7 @@
                                                  const QualType *ExpandedTypes,
                                                  unsigned NumExpandedTypes,
                                                 TypeSourceInfo **ExpandedTInfos)
-  : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
+  : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo),
     TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
     ParameterPack(true), ExpandedParameterPack(true),
     NumExpandedTypes(NumExpandedTypes)
@@ -447,6 +447,17 @@
                                            ExpandedTInfos);
 }
 
+SourceLocation NonTypeTemplateParmDecl::getInnerLocStart() const {
+  SourceLocation Start = getTypeSpecStartLoc();
+  if (Start.isInvalid())
+    Start = getLocation();
+  return Start;
+}
+
+SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
+  return SourceRange(getOuterLocStart(), getLocation());
+}
+
 SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
   return hasDefaultArgument()
     ? getDefaultArgument()->getSourceRange().getBegin()

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb  8 19:13:10 2011
@@ -820,7 +820,7 @@
                                                  ValueDecl *value) {
   // Only variables ever require capture.
   VarDecl *var = dyn_cast<VarDecl>(value);
-  if (!var || isa<NonTypeTemplateParmDecl>(var)) return CR_NoCapture;
+  if (!var) return CR_NoCapture;
 
   // Fast path: variables from the current context never require capture.
   DeclContext *DC = S.CurContext;
@@ -949,38 +949,25 @@
 
 ExprResult
 Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
-                       SourceLocation Loc, const CXXScopeSpec *SS) {
+                       SourceLocation Loc,
+                       const CXXScopeSpec *SS) {
   DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
   return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
 }
 
-/// BuildDeclRefExpr - Build a DeclRefExpr.
+/// BuildDeclRefExpr - Build an expression that references a
+/// declaration that does not require a closure capture.
 ExprResult
-Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty,
-                       ExprValueKind VK,
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
                        const DeclarationNameInfo &NameInfo,
                        const CXXScopeSpec *SS) {
-  if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) {
+  if (Ty == Context.UndeducedAutoTy) {
     Diag(NameInfo.getLoc(),
          diag::err_auto_variable_cannot_appear_in_own_initializer)
       << D->getDeclName();
     return ExprError();
   }
 
-  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
-    if (isa<NonTypeTemplateParmDecl>(VD)) {
-      // Non-type template parameters can be referenced anywhere they are
-      // visible.
-      Ty = Ty.getNonLValueExprType(Context);
-
-    // This ridiculousness brought to you by 'extern void x;' and the
-    // GNU compiler collection.
-    } else if (!getLangOptions().CPlusPlus && !Ty.hasQualifiers() &&
-               Ty->isVoidType()) {
-      VK = VK_RValue;
-    }
-  }
-
   MarkDeclarationReferenced(NameInfo.getLoc(), D);
 
   Expr *E = DeclRefExpr::Create(Context,
@@ -1694,24 +1681,6 @@
         Diag(Var->getLocation(), diag::note_global_declared_at);
       }
     }
-  } else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) {
-    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, NameLoc))
-        return ExprError();
-
-      QualType T = Func->getType();
-      QualType NoProtoType = T;
-      if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>())
-        NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType(),
-                                                     Proto->getExtInfo());
-      // Note that functions are r-values in C.
-      return BuildDeclRefExpr(Func, NoProtoType, VK_RValue, NameLoc, &SS);
-    }
   }
 
   // Check whether this might be a C++ implicit instance member access.
@@ -2325,21 +2294,6 @@
   return Owned(ULE);
 }
 
-static ExprValueKind getValueKindForDecl(ASTContext &Context,
-                                         const ValueDecl *D) {
-  // FIXME: It's not clear to me why NonTypeTemplateParmDecl is a VarDecl.
-  if (isa<VarDecl>(D) && !isa<NonTypeTemplateParmDecl>(D)) return VK_LValue;
-  if (isa<FieldDecl>(D)) return VK_LValue;
-  if (isa<IndirectFieldDecl>(D)) return VK_LValue;
-  if (!Context.getLangOptions().CPlusPlus) return VK_RValue;
-  if (isa<FunctionDecl>(D)) {
-    if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
-      return VK_RValue;
-    return VK_LValue;
-  }
-  return Expr::getValueKindForType(D->getType());
-}
-
 /// \brief Complete semantic analysis for a reference to the given declaration.
 ExprResult
 Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
@@ -2402,15 +2356,6 @@
   case CR_Error:
     return ExprError();
 
-  case CR_NoCapture: {
-    ExprValueKind VK = getValueKindForDecl(Context, VD);
-
-    // If this reference is not in a block or if the referenced
-    // variable is within the block, create a normal DeclRefExpr.
-    return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), VK,
-                            NameInfo, &SS);
-  }
-
   case CR_Capture:
     assert(!SS.isSet() && "referenced local variable with scope specifier?");
     return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ false);
@@ -2418,6 +2363,125 @@
   case CR_CaptureByRef:
     assert(!SS.isSet() && "referenced local variable with scope specifier?");
     return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ true);
+
+  case CR_NoCapture: {
+    // If this reference is not in a block or if the referenced
+    // variable is within the block, create a normal DeclRefExpr.
+
+    QualType type = VD->getType();
+    ExprValueKind valueKind;
+
+    switch (D->getKind()) {
+    // Ignore all the non-ValueDecl kinds.
+#define ABSTRACT_DECL(kind)
+#define VALUE(type, base)
+#define DECL(type, base) \
+    case Decl::type:
+#include "clang/AST/DeclNodes.inc"
+      llvm_unreachable("invalid value decl kind");
+      return ExprError();
+
+    // These shouldn't make it here.
+    case Decl::ObjCAtDefsField:
+    case Decl::ObjCIvar:
+      llvm_unreachable("forming non-member reference to ivar?");
+      return ExprError();
+
+    // Enum constants are always r-values and never references.
+    // Unresolved using declarations are dependent.
+    case Decl::EnumConstant:
+    case Decl::UnresolvedUsingValue:
+      valueKind = VK_RValue;
+      break;
+
+    // Fields and indirect fields that got here must be for
+    // pointer-to-member expressions; we just call them l-values for
+    // internal consistency, because this subexpression doesn't really
+    // exist in the high-level semantics.
+    case Decl::Field:
+    case Decl::IndirectField:
+      assert(getLangOptions().CPlusPlus &&
+             "building reference to field in C?");
+
+      // These can't have reference type in well-formed programs, but
+      // for internal consistency we do this anyway.
+      type = type.getNonReferenceType();
+      valueKind = VK_LValue;
+      break;
+
+    // Non-type template parameters are either l-values or r-values
+    // depending on the type.
+    case Decl::NonTypeTemplateParm: {
+      if (const ReferenceType *reftype = type->getAs<ReferenceType>()) {
+        type = reftype->getPointeeType();
+        valueKind = VK_LValue; // even if the parameter is an r-value reference
+        break;
+      }
+
+      // For non-references, we need to strip qualifiers just in case
+      // the template parameter was declared as 'const int' or whatever.
+      valueKind = VK_RValue;
+      type = type.getUnqualifiedType();
+      break;
+    }
+
+    case Decl::Var:
+      // In C, "extern void blah;" is valid and is an r-value.
+      if (!getLangOptions().CPlusPlus &&
+          !type.hasQualifiers() &&
+          type->isVoidType()) {
+        valueKind = VK_RValue;
+        break;
+      }
+      // fallthrough
+
+    case Decl::ImplicitParam:
+    case Decl::ParmVar:
+      // These are always l-values.
+      valueKind = VK_LValue;
+      type = type.getNonReferenceType();
+      break;
+
+    case Decl::Function: {
+      // Functions are l-values in C++.
+      if (getLangOptions().CPlusPlus) {
+        valueKind = VK_LValue;
+        break;
+      }
+      
+      // 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 (!cast<FunctionDecl>(VD)->hasPrototype())
+        if (const FunctionProtoType *proto = type->getAs<FunctionProtoType>())
+          type = Context.getFunctionNoProtoType(proto->getResultType(),
+                                                proto->getExtInfo());
+
+      // Functions are r-values in C.
+      valueKind = VK_RValue;
+      break;
+    }
+
+    case Decl::CXXMethod:
+      // C++ methods are l-values if static, r-values if non-static.
+      if (cast<CXXMethodDecl>(VD)->isStatic()) {
+        valueKind = VK_LValue;
+        break;
+      }
+      // fallthrough
+
+    case Decl::CXXConversion:
+    case Decl::CXXDestructor:
+    case Decl::CXXConstructor:
+      valueKind = VK_RValue;
+      break;
+    }
+
+    return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS);
+  }
+
   }
 
   llvm_unreachable("unknown capture result");

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Feb  8 19:13:10 2011
@@ -1168,7 +1168,7 @@
 }
 
 void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
-  VisitVarDecl(D);
+  VisitDeclaratorDecl(D);
   // TemplateParmPosition.
   D->setDepth(Record[Idx++]);
   D->setPosition(Record[Idx++]);

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Feb  8 19:13:10 2011
@@ -1009,7 +1009,7 @@
   if (D->isExpandedParameterPack())
     Record.push_back(D->getNumExpansionTypes());
   
-  VisitVarDecl(D);
+  VisitDeclaratorDecl(D);
   // TemplateParmPosition.
   Record.push_back(D->getDepth());
   Record.push_back(D->getPosition());





More information about the cfe-commits mailing list