[cfe-commits] r126139 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Decl.h include/clang/AST/DeclTemplate.h include/clang/Sema/Sema.h lib/AST/ASTContext.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateDeduction.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Feb 21 12:05:19 PST 2011


Author: rsmith
Date: Mon Feb 21 14:05:19 2011
New Revision: 126139

URL: http://llvm.org/viewvc/llvm-project?rev=126139&view=rev
Log:
Tweaks to C++0x deduced auto type support:
 * Flag indicating 'we're parsing this auto typed variable's initializer' moved from VarDecl to Sema
 * Temporary template parameter list for auto deduction is now allocated on the stack.
 * Deduced 'auto' types are now uniqued.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Feb 21 14:05:19 2011
@@ -115,6 +115,7 @@
   llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
   mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
   mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+  mutable llvm::FoldingSet<AutoType> AutoTypes;
   llvm::FoldingSet<AttributedType> AttributedTypes;
 
   mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Feb 21 14:05:19 2011
@@ -652,10 +652,6 @@
   /// slot of its function, enabling the named return value optimization (NRVO).
   bool NRVOVariable : 1;
 
-  /// \brief Whether this variable has a deduced C++0x auto type for which we're
-  /// currently parsing the initializer.
-  bool ParsingAutoInit : 1;
-  
   friend class StmtIteratorBase;
   friend class ASTDeclReader;
   
@@ -665,7 +661,7 @@
           StorageClass SCAsWritten)
     : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
       ThreadSpecified(false), HasCXXDirectInit(false),
-      ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) {
+      ExceptionVar(false), NRVOVariable(false) {
     SClass = SC;
     SClassAsWritten = SCAsWritten;
   }
@@ -889,18 +885,6 @@
 
   void setInit(Expr *I);
 
-  /// \brief Check whether we are in the process of parsing an initializer
-  /// needed to deduce the type of this variable.
-  bool isParsingAutoInit() const {
-    return ParsingAutoInit;
-  }
-
-  /// \brief Note whether we are currently parsing an initializer needed to
-  /// deduce the type of this variable.
-  void setParsingAutoInit(bool P) {
-    ParsingAutoInit = P;
-  }
-
   EvaluatedStmt *EnsureEvaluatedStmt() const {
     EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
     if (!Eval) {

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Mon Feb 21 14:05:19 2011
@@ -48,6 +48,7 @@
   /// parameter list.
   unsigned NumParams;
 
+protected:
   TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
                         NamedDecl **Params, unsigned NumParams,
                         SourceLocation RAngleLoc);
@@ -107,6 +108,19 @@
   }
 };
 
+/// FixedSizeTemplateParameterList - Stores a list of template parameters for a
+/// TemplateDecl and its derived classes. Suitable for creating on the stack.
+template<size_t N>
+class FixedSizeTemplateParameterList : public TemplateParameterList {
+  NamedDecl *Params[N];
+
+public:
+  FixedSizeTemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+                                 NamedDecl **Params, SourceLocation RAngleLoc) :
+    TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) {
+  }
+};
+
 /// \brief A template argument list.
 class TemplateArgumentList {
   /// \brief The template argument list.
@@ -914,6 +928,9 @@
     TypeForDecl = Type.getTypePtrOrNull();
   }
 
+  /// Sema creates these on the stack during auto type deduction.
+  friend class Sema;
+
 public:
   static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
                                       SourceLocation L, unsigned D, unsigned P,

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Feb 21 14:05:19 2011
@@ -267,6 +267,10 @@
   /// same list more than once.
   llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet;
 
+  /// ParsingInitForAutoVars - a set of declarations with auto types for which
+  /// we are currently parsing the initializer.
+  llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;
+
   /// \brief A mapping from external names to the most recent
   /// locally-scoped external declaration with that name.
   ///
@@ -856,6 +860,7 @@
   void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
   void ActOnInitializerError(Decl *Dcl);
   void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+  void FinalizeDeclaration(Decl *D);
   DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
                                          Decl **Group,
                                          unsigned NumDecls);

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Feb 21 14:05:19 2011
@@ -2683,12 +2683,22 @@
   return QualType(dt, 0);
 }
 
-/// getAutoType - Unlike many "get<Type>" functions, we don't unique
-/// AutoType AST's.
+/// getAutoType - We only unique auto types after they've been deduced.
 QualType ASTContext::getAutoType(QualType DeducedType) const {
-  AutoType *at = new (*this, TypeAlignment) AutoType(DeducedType);
-  Types.push_back(at);
-  return QualType(at, 0);
+  void *InsertPos = 0;
+  if (!DeducedType.isNull()) {
+    // Look in the folding set for an existing type.
+    llvm::FoldingSetNodeID ID;
+    AutoType::Profile(ID, DeducedType);
+    if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
+      return QualType(AT, 0);
+  }
+
+  AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType);
+  Types.push_back(AT);
+  if (InsertPos)
+    AutoTypes.InsertNode(AT, InsertPos);
+  return QualType(AT, 0);
 }
 
 /// getTagDeclType - Return the unique reference to the type for the

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Feb 21 14:05:19 2011
@@ -667,6 +667,8 @@
     Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto);
   }
 
+  Actions.FinalizeDeclaration(ThisDecl);
+
   return ThisDecl;
 }
 

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Feb 21 14:05:19 2011
@@ -836,6 +836,8 @@
   
   // FIXME: Build a reference to this declaration? Convert it to bool?
   // (This is currently handled by Sema).
+
+  Actions.FinalizeDeclaration(DeclOut);
   
   return false;
 }

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon Feb 21 14:05:19 2011
@@ -466,6 +466,12 @@
     checkUndefinedInternals(*this);
   }
 
+  // Check we've noticed that we're no longer parsing the initializer for every
+  // variable. If we miss cases, then at best we have a performance issue and
+  // at worst a rejects-valid bug.
+  assert(ParsingInitForAutoVars.empty() &&
+         "Didn't unmark var as having its initializer parsed");
+
   TUScope = 0;
 }
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Feb 21 14:05:19 2011
@@ -3026,11 +3026,11 @@
     NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
                             II, R, TInfo, SC, SCAsWritten);
 
-    // If this decl has an auto type in need of deduction, mark the VarDecl so
-    // we can diagnose uses of it in its own initializer.
-    if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto) {
-      NewVD->setParsingAutoInit(R->getContainedAutoType());
-    }
+    // If this decl has an auto type in need of deduction, make a note of the
+    // Decl so we can diagnose uses of it in its own initializer.
+    if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+        R->getContainedAutoType())
+      ParsingInitForAutoVars.insert(NewVD);
 
     if (D.isInvalidType() || Invalid)
       NewVD->setInvalidDecl();
@@ -4534,8 +4534,6 @@
 
   // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
   if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
-    VDecl->setParsingAutoInit(false);
-
     QualType DeducedType;
     if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
       Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
@@ -4800,9 +4798,8 @@
   if (!VD) return;
 
   // Auto types are meaningless if we can't make sense of the initializer.
-  if (VD->isParsingAutoInit()) {
-    VD->setParsingAutoInit(false);
-    VD->setInvalidDecl();
+  if (ParsingInitForAutoVars.count(D)) {
+    D->setInvalidDecl();
     return;
   }
 
@@ -4840,8 +4837,6 @@
 
     // C++0x [dcl.spec.auto]p3
     if (TypeMayContainAuto && Type->getContainedAutoType()) {
-      Var->setParsingAutoInit(false);
-
       Diag(Var->getLocation(), diag::err_auto_var_requires_init)
         << Var->getDeclName() << Type;
       Var->setInvalidDecl();
@@ -5044,6 +5039,14 @@
     FinalizeVarWithDestructor(var, recordType);
 }
 
+/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
+/// any semantic actions necessary after any initializer has been attached.
+void
+Sema::FinalizeDeclaration(Decl *ThisDecl) {
+  // Note that we are no longer parsing the initializer for this declaration.
+  ParsingInitForAutoVars.erase(ThisDecl);
+}
+
 Sema::DeclGroupPtrTy
 Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
                               Decl **Group, unsigned NumDecls) {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Feb 21 14:05:19 2011
@@ -1078,6 +1078,8 @@
   if (Deleted) // FIXME: Source location is not very good.
     SetDeclDeleted(Member, D.getSourceRange().getBegin());
 
+  FinalizeDeclaration(Member);
+
   if (isInstField)
     FieldCollector->Add(cast<FieldDecl>(Member));
   return Member;
@@ -5972,8 +5974,6 @@
 
   // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
   if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
-    VDecl->setParsingAutoInit(false);
-
     // FIXME: n3225 doesn't actually seem to indicate this is ill-formed
     if (Exprs.size() > 1) {
       Diag(Exprs.get()[1]->getSourceRange().getBegin(),

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Feb 21 14:05:19 2011
@@ -76,12 +76,10 @@
   }
 
   // See if this is an auto-typed variable whose initializer we are parsing.
-  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
-    if (VD->isParsingAutoInit()) {
-      Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
-        << D->getDeclName();
-      return true;
-    }
+  if (ParsingInitForAutoVars.count(D)) {
+    Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+      << D->getDeclName();
+    return true;
   }
 
   // See if the decl is deprecated.

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Mon Feb 21 14:05:19 2011
@@ -3004,12 +3004,12 @@
   LocalInstantiationScope InstScope(*this);
 
   // Build template<class TemplParam> void Func(FuncParam);
-  NamedDecl *TemplParam
-    = TemplateTypeParmDecl::Create(Context, 0, Loc, 0, 0, 0, false, false);
-  TemplateParameterList *TemplateParams
-    = TemplateParameterList::Create(Context, Loc, Loc, &TemplParam, 1, Loc);
-
   QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false);
+  TemplateTypeParmDecl TemplParam(0, Loc, 0, false, TemplArg, false);
+  NamedDecl *TemplParamPtr = &TemplParam;
+  FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
+                                                   Loc);
+
   QualType FuncParam =
     SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
 
@@ -3018,13 +3018,13 @@
   Deduced.resize(1);
   QualType InitType = Init->getType();
   unsigned TDF = 0;
-  if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+  if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
                                                 FuncParam, InitType, Init,
                                                 TDF))
     return false;
 
   TemplateDeductionInfo Info(Context, Loc);
-  if (::DeduceTemplateArguments(*this, TemplateParams,
+  if (::DeduceTemplateArguments(*this, &TemplateParams,
                                 FuncParam, InitType, Info, Deduced,
                                 TDF))
     return false;

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp?rev=126139&r1=126138&r2=126139&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp Mon Feb 21 14:05:19 2011
@@ -3,12 +3,19 @@
   auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}}
   auto *b = b; // expected-error{{variable 'b' declared with 'auto' type cannot appear in its own initializer}}
   const auto c = c; // expected-error{{variable 'c' declared with 'auto' type cannot appear in its own initializer}}
+  if (auto d = d) {} // expected-error {{variable 'd' declared with 'auto' type cannot appear in its own initializer}}
+  auto e = ({ auto f = e; 0; }); // expected-error {{variable 'e' declared with 'auto' type cannot appear in its own initializer}}
 }
 
 void g() {
   auto a; // expected-error{{declaration of variable 'a' with type 'auto' requires an initializer}}
   
   auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}}
+
+  if (auto b) {} // expected-error {{expected '='}}
+  for (;auto b;) {} // expected-error {{expected '='}}
+  while (auto b) {} // expected-error {{expected '='}}
+  if (auto b = true) { (void)b; }
 }
 
 auto n(1,2,3); // expected-error{{initializer for variable 'n' with type 'auto' contains multiple expressions}}
@@ -21,7 +28,7 @@
 void h() {
   auto b = 42ULL;
 
-  for (auto c = 0; c < 100; ++c) {
+  for (auto c = 0; c < b; ++c) {
   }
 }
 





More information about the cfe-commits mailing list