Add type source information for both kinds of typeof types.
Patch by Enea Zaffanella.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93344 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 3e74d07..c36c0ff 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -1029,18 +1029,88 @@
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.
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index 06d0e47..6a3d8a9 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -194,6 +194,7 @@
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 @@
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);
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 3ccb7a9..0840c52 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -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 @@
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());
+}
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 4c6e5f4..07d5a78 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2111,10 +2111,15 @@
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++]));
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 84a8a45..3f6841b 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -344,10 +344,15 @@
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);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 1e8e33e..66a6957 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -3154,6 +3154,8 @@
Token OpTok = Tok;
SourceLocation StartLoc = ConsumeToken();
+ const bool hasParens = Tok.is(tok::l_paren);
+
bool isCastExpr;
TypeTy *CastTy;
SourceRange CastRange;
@@ -3161,6 +3163,8 @@
isCastExpr,
CastTy,
CastRange);
+ if (hasParens)
+ DS.setTypeofParensRange(CastRange);
if (CastRange.getEnd().isInvalid())
// FIXME: Not accurate, the range gets one token more than it should.
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 7c0460d..9515834 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1360,6 +1360,20 @@
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());
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index e966daa..419dd9c 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2619,18 +2619,16 @@
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 @@
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 @@
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;
}