[cfe-commits] r116281 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/AST/ASTContext.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h test/SemaCXX/alignof-sizeof-reference.cpp test/SemaCXX/decltype-overloaded-functions.cpp

John McCall rjmccall at apple.com
Mon Oct 11 17:20:44 PDT 2010


Author: rjmccall
Date: Mon Oct 11 19:20:44 2010
New Revision: 116281

URL: http://llvm.org/viewvc/llvm-project?rev=116281&view=rev
Log:
Add some infrastructure for dealing with expressions of 'placeholder' type,
i.e. expressions with an internally-convenient type which should not be
appearing in generally valid, complete ASTs.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp
    cfe/trunk/test/SemaCXX/decltype-overloaded-functions.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Oct 11 19:20:44 2010
@@ -388,9 +388,8 @@
   CanQualType FloatTy, DoubleTy, LongDoubleTy;
   CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
   CanQualType VoidPtrTy, NullPtrTy;
-  CanQualType OverloadTy;
+  CanQualType OverloadTy, UndeducedAutoTy;
   CanQualType DependentTy;
-  CanQualType UndeducedAutoTy;
   CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
 
   ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Oct 11 19:20:44 2010
@@ -867,6 +867,12 @@
   /// isSpecificBuiltinType - Test for a particular builtin type.
   bool isSpecificBuiltinType(unsigned K) const;
 
+  /// isPlaceholderType - Test for a type which does not represent an
+  /// actual type-system type but is instead used as a placeholder for
+  /// various convenient purposes within Clang.  All such types are
+  /// BuiltinTypes.
+  bool isPlaceholderType() const;
+
   /// isIntegerType() does *not* include complex integers (a GCC extension).
   /// isComplexIntegerType() can be used to test for complex integers.
   bool isIntegerType() const;     // C99 6.2.5p17 (int, char, bool, enum)
@@ -1105,8 +1111,13 @@
 
     NullPtr,  // This is the type of C++0x 'nullptr'.
 
+    /// This represents the type of an expression whose type is
+    /// totally unknown, e.g. 'T::foo'.  It is permitted for this to
+    /// appear in situations where the structure of the type is
+    /// theoretically deducible.
+    Dependent,
+
     Overload,  // This represents the type of an overloaded function declaration.
-    Dependent, // This represents the type of a type-dependent expression.
 
     UndeducedAuto, // In C++0x, this represents the type of an auto variable
                    // that has not been deduced yet.
@@ -1156,6 +1167,14 @@
     return TypeKind >= Float && TypeKind <= LongDouble;
   }
 
+  /// Determines whether this type is a "forbidden" placeholder type,
+  /// i.e. a type which cannot appear in arbitrary positions in a
+  /// fully-formed expression.
+  bool isPlaceholderType() const {
+    return TypeKind == Overload ||
+           TypeKind == UndeducedAuto;
+  }
+
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
   static bool classof(const BuiltinType *) { return true; }
 };
@@ -3612,6 +3631,12 @@
   return false;
 }
 
+inline bool Type::isPlaceholderType() const {
+  if (const BuiltinType *BT = getAs<BuiltinType>())
+    return BT->isPlaceholderType();
+  return false;
+}
+
 /// \brief Determines whether this is a type for which one can define
 /// an overloaded operator.
 inline bool Type::isOverloadableType() const {

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Oct 11 19:20:44 2010
@@ -800,8 +800,7 @@
 
 // C++0x decltype
 def err_cannot_determine_declared_type_of_overloaded_function : Error<
-    "cannot determine the %select{type|declared type}0 of an overloaded "
-    "function">;
+    "cannot determine the type of an overloaded function">;
     
 // C++0x auto
 def err_auto_variable_cannot_appear_in_own_initializer : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct 11 19:20:44 2010
@@ -646,8 +646,8 @@
   QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
                              const CXXScopeSpec &SS, QualType T);
 
-  QualType BuildTypeofExprType(Expr *E);
-  QualType BuildDecltypeType(Expr *E);
+  QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
+  QualType BuildDecltypeType(Expr *E, SourceLocation Loc);
 
   //===--------------------------------------------------------------------===//
   // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
@@ -1758,9 +1758,10 @@
     ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
                            void *TyOrEx, const SourceRange &ArgRange);
 
-  bool CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &R);
+  ExprResult CheckPlaceholderExpr(Expr *E, SourceLocation Loc);
+
   bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
-                                 const SourceRange &R, bool isSizeof);
+                                 SourceRange R, bool isSizeof);
 
   ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
                                  tok::TokenKind Kind, Expr *Input);

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Oct 11 19:20:44 2010
@@ -329,9 +329,6 @@
   else // C99
     Char32Ty = getFromTargetType(Target.getChar32Type());
 
-  // Placeholder type for functions.
-  InitBuiltinType(OverloadTy,          BuiltinType::Overload);
-
   // Placeholder type for type-dependent expressions whose type is
   // completely unknown. No code should ever check a type against
   // DependentTy and users should never see it; however, it is here to
@@ -339,9 +336,12 @@
   // expressions.
   InitBuiltinType(DependentTy,         BuiltinType::Dependent);
 
+  // Placeholder type for functions.
+  InitBuiltinType(OverloadTy,          BuiltinType::Overload);
+
   // Placeholder type for C++0x auto declarations whose real type has
   // not yet been deduced.
-  InitBuiltinType(UndeducedAutoTy, BuiltinType::UndeducedAuto);
+  InitBuiltinType(UndeducedAutoTy,     BuiltinType::UndeducedAuto);
 
   // C99 6.2.5p11.
   FloatComplexTy      = getComplexType(FloatTy);

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Oct 11 19:20:44 2010
@@ -2121,7 +2121,7 @@
 /// See C99 6.3.2.1p[2-4] for more details.
 bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
                                      SourceLocation OpLoc,
-                                     const SourceRange &ExprRange,
+                                     SourceRange ExprRange,
                                      bool isSizeof) {
   if (exprType->isDependentType())
     return false;
@@ -2160,17 +2160,11 @@
     return true;
   }
 
-  if (Context.hasSameUnqualifiedType(exprType, Context.OverloadTy)) {
-    Diag(OpLoc, diag::err_sizeof_alignof_overloaded_function_type)
-      << !isSizeof << ExprRange;
-    return true;
-  }
-  
   return false;
 }
 
-bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc,
-                            const SourceRange &ExprRange) {
+static bool CheckAlignOfExpr(Sema &S, Expr *E, SourceLocation OpLoc,
+                             SourceRange ExprRange) {
   E = E->IgnoreParens();
 
   // alignof decl is always ok.
@@ -2182,7 +2176,7 @@
     return false;
 
   if (E->getBitField()) {
-    Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 1 << ExprRange;
+   S. Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 1 << ExprRange;
     return true;
   }
 
@@ -2192,7 +2186,7 @@
     if (isa<FieldDecl>(ME->getMemberDecl()))
       return false;
 
-  return CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
+  return S.CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
 }
 
 /// \brief Build a sizeof or alignof expression given a type operand.
@@ -2220,12 +2214,16 @@
 ExprResult
 Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
                               bool isSizeOf, SourceRange R) {
+  ExprResult PResult = CheckPlaceholderExpr(E, OpLoc);
+  if (PResult.isInvalid()) return ExprError();
+  E = PResult.take();
+
   // Verify that the operand is valid.
   bool isInvalid = false;
   if (E->isTypeDependent()) {
     // Delay type-checking for type-dependent expressions.
   } else if (!isSizeOf) {
-    isInvalid = CheckAlignOfExpr(E, OpLoc, R);
+    isInvalid = CheckAlignOfExpr(*this, E, OpLoc, R);
   } else if (E->getBitField()) {  // C99 6.5.3.4p1.
     Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
     isInvalid = true;
@@ -8107,3 +8105,35 @@
   
   return Owned(Sub);
 }
+
+/// Check for operands with placeholder types and complain if found.
+/// Returns true if there was an error and no recovery was possible.
+ExprResult Sema::CheckPlaceholderExpr(Expr *E, SourceLocation Loc) {
+  const BuiltinType *BT = E->getType()->getAs<BuiltinType>();
+  if (!BT || !BT->isPlaceholderType()) return Owned(E);
+
+  // If this is overload, check for a single overload.
+  if (BT->getKind() == BuiltinType::Overload) {
+    if (FunctionDecl *Specialization
+          = ResolveSingleFunctionTemplateSpecialization(E)) {
+      // The access doesn't really matter in this case.
+      DeclAccessPair Found = DeclAccessPair::make(Specialization,
+                                                  Specialization->getAccess());
+      E = FixOverloadedFunctionReference(E, Found, Specialization);
+      if (!E) return ExprError();
+      return Owned(E);
+    }
+
+    Diag(Loc, diag::err_cannot_determine_declared_type_of_overloaded_function)
+      << E->getSourceRange();
+    return ExprError();
+  }
+
+  // Otherwise it's a use of undeduced auto.
+  assert(BT->getKind() == BuiltinType::UndeducedAuto);
+
+  DeclRefExpr *DRE = cast<DeclRefExpr>(E->IgnoreParens());
+  Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+    << DRE->getDecl() << E->getSourceRange();
+  return ExprError();
+}

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Oct 11 19:20:44 2010
@@ -350,7 +350,7 @@
     Expr *E = DS.getRepAsExpr();
     assert(E && "Didn't get an expression for typeof?");
     // TypeQuals handled by caller.
-    Result = TheSema.BuildTypeofExprType(E);
+    Result = TheSema.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
     if (Result.isNull()) {
       Result = Context.IntTy;
       TheDeclarator.setInvalidType(true);
@@ -361,7 +361,7 @@
     Expr *E = DS.getRepAsExpr();
     assert(E && "Didn't get an expression for decltype?");
     // TypeQuals handled by caller.
-    Result = TheSema.BuildDecltypeType(E);
+    Result = TheSema.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
     if (Result.isNull()) {
       Result = Context.IntTy;
       TheDeclarator.setInvalidType(true);
@@ -2196,25 +2196,11 @@
   return Context.getElaboratedType(Keyword, NNS, T);
 }
 
-QualType Sema::BuildTypeofExprType(Expr *E) {
-  if (E->getType() == Context.OverloadTy) {
-    // C++ [temp.arg.explicit]p3 allows us to resolve a template-id to a 
-    // function template specialization wherever deduction cannot occur.
-    if (FunctionDecl *Specialization
-        = ResolveSingleFunctionTemplateSpecialization(E)) {
-      // The access doesn't really matter in this case.
-      DeclAccessPair Found = DeclAccessPair::make(Specialization,
-                                                  Specialization->getAccess());
-      E = FixOverloadedFunctionReference(E, Found, Specialization);
-      if (!E)
-        return QualType();      
-    } else {
-      Diag(E->getLocStart(),
-           diag::err_cannot_determine_declared_type_of_overloaded_function)
-        << false << E->getSourceRange();
-      return QualType();
-    }
-  }
+QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
+  ExprResult ER = CheckPlaceholderExpr(E, Loc);
+  if (ER.isInvalid()) return QualType();
+  E = ER.take();
+
   if (!E->isTypeDependent()) {
     QualType T = E->getType();
     if (const TagType *TT = T->getAs<TagType>())
@@ -2223,25 +2209,10 @@
   return Context.getTypeOfExprType(E);
 }
 
-QualType Sema::BuildDecltypeType(Expr *E) {
-  if (E->getType() == Context.OverloadTy) {
-    // C++ [temp.arg.explicit]p3 allows us to resolve a template-id to a 
-    // function template specialization wherever deduction cannot occur.
-    if (FunctionDecl *Specialization
-          = ResolveSingleFunctionTemplateSpecialization(E)) {
-      // The access doesn't really matter in this case.
-      DeclAccessPair Found = DeclAccessPair::make(Specialization,
-                                                  Specialization->getAccess());
-      E = FixOverloadedFunctionReference(E, Found, Specialization);
-      if (!E)
-        return QualType();      
-    } else {
-      Diag(E->getLocStart(),
-           diag::err_cannot_determine_declared_type_of_overloaded_function)
-        << true << E->getSourceRange();
-      return QualType();
-    }
-  }
+QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
+  ExprResult ER = CheckPlaceholderExpr(E, Loc);
+  if (ER.isInvalid()) return QualType();
+  E = ER.take();
   
   return Context.getDecltypeType(E);
 }

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Oct 11 19:20:44 2010
@@ -495,7 +495,7 @@
   ///
   /// By default, performs semantic analysis when building the typeof type.
   /// Subclasses may override this routine to provide different behavior.
-  QualType RebuildTypeOfExprType(Expr *Underlying);
+  QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc);
 
   /// \brief Build a new typeof(type) type.
   ///
@@ -506,7 +506,7 @@
   ///
   /// By default, performs semantic analysis when building the decltype type.
   /// Subclasses may override this routine to provide different behavior.
-  QualType RebuildDecltypeType(Expr *Underlying);
+  QualType RebuildDecltypeType(Expr *Underlying, SourceLocation Loc);
 
   /// \brief Build a new template specialization type.
   ///
@@ -3065,7 +3065,7 @@
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() ||
       E.get() != TL.getUnderlyingExpr()) {
-    Result = getDerived().RebuildTypeOfExprType(E.get());
+    Result = getDerived().RebuildTypeOfExprType(E.get(), TL.getTypeofLoc());
     if (Result.isNull())
       return QualType();
   }
@@ -3120,7 +3120,7 @@
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() ||
       E.get() != T->getUnderlyingExpr()) {
-    Result = getDerived().RebuildDecltypeType(E.get());
+    Result = getDerived().RebuildDecltypeType(E.get(), TL.getNameLoc());
     if (Result.isNull())
       return QualType();
   }
@@ -6502,8 +6502,9 @@
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E) {
-  return SemaRef.BuildTypeofExprType(E);
+QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E,
+                                                       SourceLocation Loc) {
+  return SemaRef.BuildTypeofExprType(E, Loc);
 }
 
 template<typename Derived>
@@ -6512,8 +6513,9 @@
 }
 
 template<typename Derived>
-QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E) {
-  return SemaRef.BuildDecltypeType(E);
+QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E,
+                                                     SourceLocation Loc) {
+  return SemaRef.BuildDecltypeType(E, Loc);
 }
 
 template<typename Derived>

Modified: cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp (original)
+++ cfe/trunk/test/SemaCXX/alignof-sizeof-reference.cpp Mon Oct 11 19:20:44 2010
@@ -11,5 +11,5 @@
 void f(); 
 void f(int); 
 void g() { 
-  sizeof(&f); // expected-error{{invalid application of 'sizeof' to an overloaded function}}
+  sizeof(&f); // expected-error{{cannot determine the type of an overloaded function}}
 }

Modified: cfe/trunk/test/SemaCXX/decltype-overloaded-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/decltype-overloaded-functions.cpp?rev=116281&r1=116280&r2=116281&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/decltype-overloaded-functions.cpp (original)
+++ cfe/trunk/test/SemaCXX/decltype-overloaded-functions.cpp Mon Oct 11 19:20:44 2010
@@ -2,10 +2,10 @@
 
 void f();
 void f(int);
-decltype(f) a; // expected-error{{cannot determine the declared type of an overloaded function}}
+decltype(f) a; // expected-error{{cannot determine the type of an overloaded function}}
 
 template<typename T> struct S {
-  decltype(T::f) * f; // expected-error{{cannot determine the declared type of an overloaded function}}
+  decltype(T::f) * f; // expected-error{{cannot determine the type of an overloaded function}}
 };
 
 struct K { void f(); void f(int); };





More information about the cfe-commits mailing list