]> granicus.if.org Git - clang/commitdiff
Add type source information for both kinds of typeof types.
authorJohn McCall <rjmccall@apple.com>
Wed, 13 Jan 2010 20:03:27 +0000 (20:03 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 13 Jan 2010 20:03:27 +0000 (20:03 +0000)
Patch by Enea Zaffanella.

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

include/clang/AST/TypeLoc.h
include/clang/Parse/DeclSpec.h
lib/AST/TypeLoc.cpp
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Parse/ParseDecl.cpp
lib/Sema/SemaType.cpp
lib/Sema/TreeTransform.h

index 3e74d07ff7f34e590cad240ce376f305430820cc..c36c0ffde32ed785637bc1e6b49d6ac9d976b07c 100644 (file)
@@ -1029,18 +1029,88 @@ class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                                         ComplexType> {
 };
 
-// FIXME: location of the 'typeof' and parens (the expression is
-// carried by the type).
-class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
-                                                           TypeOfExprTypeLoc,
-                                                           TypeOfExprType> {
+struct TypeofLocInfo {
+  SourceLocation TypeofLoc;
+  SourceLocation LParenLoc;
+  SourceLocation RParenLoc;
 };
 
-// FIXME: location of the 'typeof' and parens; also the TypeSourceInfo
-// for the inner type, or (maybe) just express that inline to the TypeLoc.
-class TypeOfTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
-                                                       TypeOfTypeLoc,
-                                                       TypeOfType> {
+struct TypeOfExprTypeLocInfo : public TypeofLocInfo {
+};
+
+struct TypeOfTypeLocInfo : public TypeofLocInfo {
+  TypeSourceInfo* UnderlyingTInfo;
+};
+
+template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
+class TypeofLikeTypeLoc
+  : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {
+public:
+  SourceLocation getTypeofLoc() const {
+    return this->getLocalData()->TypeofLoc;
+  }
+  void setTypeofLoc(SourceLocation Loc) {
+    this->getLocalData()->TypeofLoc = Loc;
+  }
+
+  SourceLocation getLParenLoc() const {
+    return this->getLocalData()->LParenLoc;
+  }
+  void setLParenLoc(SourceLocation Loc) {
+    this->getLocalData()->LParenLoc = Loc;
+  }
+
+  SourceLocation getRParenLoc() const {
+    return this->getLocalData()->RParenLoc;
+  }
+  void setRParenLoc(SourceLocation Loc) {
+    this->getLocalData()->RParenLoc = Loc;
+  }
+
+  SourceRange getParensRange() const {
+    return SourceRange(getLParenLoc(), getRParenLoc());
+  }
+  void setParensRange(SourceRange range) {
+      setLParenLoc(range.getBegin());
+      setRParenLoc(range.getEnd());
+  }
+
+  SourceRange getSourceRange() const {
+    return SourceRange(getTypeofLoc(), getRParenLoc());
+  }
+
+  void initializeLocal(SourceLocation Loc) {
+    setTypeofLoc(Loc);
+    setLParenLoc(Loc);
+    setRParenLoc(Loc);
+  }
+};
+
+class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
+                                                   TypeOfExprType,
+                                                   TypeOfExprTypeLocInfo> {
+public:
+  Expr* getUnderlyingExpr() const {
+    return getTypePtr()->getUnderlyingExpr();
+  }
+  // Reimplemented to account for GNU/C++ extension
+  //     typeof unary-expression
+  // where there are no parentheses.
+  SourceRange getSourceRange() const;
+};
+
+class TypeOfTypeLoc
+  : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {
+public:
+  QualType getUnderlyingType() const {
+    return this->getTypePtr()->getUnderlyingType();
+  }
+  TypeSourceInfo* getUnderlyingTInfo() const {
+    return this->getLocalData()->UnderlyingTInfo;
+  }
+  void setUnderlyingTInfo(TypeSourceInfo* TI) const {
+    this->getLocalData()->UnderlyingTInfo = TI;
+  }
 };
 
 // FIXME: location of the 'decltype' and parens.
index 06d0e4745a49833f78c139b96c62caf97bfa8eca..6a3d8a924e077e863e1a191c38eda752ad998e6a 100644 (file)
@@ -194,6 +194,7 @@ private:
 
   SourceLocation StorageClassSpecLoc, SCS_threadLoc;
   SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc;
+  SourceRange TypeofParensRange;
   SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
   SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc;
   SourceLocation FriendLoc, ConstexprLoc;
@@ -257,6 +258,9 @@ public:
   SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
   SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
 
+  SourceRange getTypeofParensRange() const { return TypeofParensRange; }
+  void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; }
+
   /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool"
   /// or "union".
   static const char *getSpecifierName(DeclSpec::TST T);
index 3ccb7a9cc613cd7803cb9c99ba07d969d04f78bf..0840c52b4c2026e291969b30138279724a2e2be6 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "llvm/Support/raw_ostream.h"
 #include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/Expr.h"
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -123,3 +124,14 @@ bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
   if (TL->getType().hasLocalQualifiers()) return false;
   return TSTChecker().Visit(*TL);
 }
+
+// Reimplemented to account for GNU/C++ extension
+//     typeof unary-expression
+// where there are no parentheses.
+SourceRange TypeOfExprTypeLoc::getSourceRange() const {
+  if (getRParenLoc().isValid())
+    return SourceRange(getTypeofLoc(), getRParenLoc());
+  else
+    return SourceRange(getTypeofLoc(),
+                       getUnderlyingExpr()->getSourceRange().getEnd());
+}
index 4c6e5f44a0e2760af948740886e7e71730fb46fd..07d5a78beaeb65e2b25fc59137866ea698c24c63 100644 (file)
@@ -2111,10 +2111,15 @@ void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
   TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
 void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
 void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(Record, Idx));
 }
 void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
   TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
index 84a8a450b0c238bb514b5d1745072ae95c1717db..3f6841b54576aebc639c00911c1ed6c5d6f5adc6 100644 (file)
@@ -344,10 +344,15 @@ void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }
 void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+  Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
+  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
 }
 void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+  Writer.AddSourceLocation(TL.getTypeofLoc(), Record);
+  Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+  Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+  Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record);
 }
 void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
index 1e8e33ebd84d29c1e09f5415d77717ef0757772e..66a69574433ed6d1f055cb30233434bfe0ea471b 100644 (file)
@@ -3154,6 +3154,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
   Token OpTok = Tok;
   SourceLocation StartLoc = ConsumeToken();
 
+  const bool hasParens = Tok.is(tok::l_paren);
+
   bool isCastExpr;
   TypeTy *CastTy;
   SourceRange CastRange;
@@ -3161,6 +3163,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
                                                                isCastExpr,
                                                                CastTy,
                                                                CastRange);
+  if (hasParens)
+    DS.setTypeofParensRange(CastRange);
 
   if (CastRange.getEnd().isInvalid())
     // FIXME: Not accurate, the range gets one token more than it should.
index 7c0460dbedfeac51bbd7f1342db61f883e6e7bc4..9515834bb84a2b963b6e20a1ee62038e06141a67 100644 (file)
@@ -1360,6 +1360,20 @@ namespace {
         cast<TemplateSpecializationTypeLoc>(TInfo->getTypeLoc());
       TL.copy(OldTL);
     }
+    void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+      assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
+      TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
+      TL.setParensRange(DS.getTypeofParensRange());
+    }
+    void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+      assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
+      TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
+      TL.setParensRange(DS.getTypeofParensRange());
+      assert(DS.getTypeRep());
+      TypeSourceInfo *TInfo = 0;
+      Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+      TL.setUnderlyingTInfo(TInfo);
+    }
     void VisitTypeLoc(TypeLoc TL) {
       // FIXME: add other typespec types and change this to an assert.
       TL.initialize(DS.getTypeSpecTypeLoc());
index e966daa9764e3083f51d589147338c43c530faa1..419dd9c00f96ef912699ec377aad3d5678af4e28 100644 (file)
@@ -2619,18 +2619,16 @@ QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
                                                       TypeOfExprTypeLoc TL) {
-  TypeOfExprType *T = TL.getTypePtr();
-
   // typeof expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
 
-  Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
+  Sema::OwningExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr());
   if (E.isInvalid())
     return QualType();
 
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() ||
-      E.get() != T->getUnderlyingExpr()) {
+      E.get() != TL.getUnderlyingExpr()) {
     Result = getDerived().RebuildTypeOfExprType(move(E));
     if (Result.isNull())
       return QualType();
@@ -2638,7 +2636,9 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
   else E.take();
 
   TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result);
-  NewTL.setNameLoc(TL.getNameLoc());
+  NewTL.setTypeofLoc(TL.getTypeofLoc());
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
 
   return Result;
 }
@@ -2646,23 +2646,23 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
                                                      TypeOfTypeLoc TL) {
-  TypeOfType *T = TL.getTypePtr();
-
-  // FIXME: should be an inner type, or at least have a TypeSourceInfo.
-  QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
-  if (Underlying.isNull())
+  TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo();
+  TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI);
+  if (!New_Under_TI)
     return QualType();
 
   QualType Result = TL.getType();
-  if (getDerived().AlwaysRebuild() ||
-      Underlying != T->getUnderlyingType()) {
-    Result = getDerived().RebuildTypeOfType(Underlying);
+  if (getDerived().AlwaysRebuild() || New_Under_TI != Old_Under_TI) {
+    Result = getDerived().RebuildTypeOfType(New_Under_TI->getType());
     if (Result.isNull())
       return QualType();
   }
 
   TypeOfTypeLoc NewTL = TLB.push<TypeOfTypeLoc>(Result);
-  NewTL.setNameLoc(TL.getNameLoc());
+  NewTL.setTypeofLoc(TL.getTypeofLoc());
+  NewTL.setLParenLoc(TL.getLParenLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
+  NewTL.setUnderlyingTInfo(New_Under_TI);
 
   return Result;
 }