aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp34
-rw-r--r--clang/lib/AST/ASTImporter.cpp11
-rw-r--r--clang/lib/AST/ASTStructuralEquivalence.cpp4
-rw-r--r--clang/lib/AST/ODRHash.cpp2
-rw-r--r--clang/lib/AST/Type.cpp24
-rw-r--r--clang/lib/AST/TypeLoc.cpp4
-rw-r--r--clang/lib/AST/TypePrinter.cpp6
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp2
-rw-r--r--clang/lib/Parse/ParseDecl.cpp39
-rw-r--r--clang/lib/Parse/ParseExpr.cpp18
-rw-r--r--clang/lib/Sema/DeclSpec.cpp4
-rw-r--r--clang/lib/Sema/SemaDecl.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp3
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp2
-rw-r--r--clang/lib/Sema/SemaType.cpp27
-rw-r--r--clang/lib/Sema/TreeTransform.h31
-rw-r--r--clang/lib/Serialization/ASTReader.cpp2
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp2
19 files changed, 148 insertions, 71 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 99ab66d..f264223 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5581,30 +5581,31 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
/// multiple declarations that refer to "typeof(x)" all contain different
/// DeclRefExpr's. This doesn't effect the type checker, since it operates
/// on canonical type's (which are always unique).
-QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const {
+QualType ASTContext::getTypeOfExprType(Expr *tofExpr, TypeOfKind Kind) const {
TypeOfExprType *toe;
if (tofExpr->isTypeDependent()) {
llvm::FoldingSetNodeID ID;
- DependentTypeOfExprType::Profile(ID, *this, tofExpr);
+ DependentTypeOfExprType::Profile(ID, *this, tofExpr,
+ Kind == TypeOfKind::Unqualified);
void *InsertPos = nullptr;
- DependentTypeOfExprType *Canon
- = DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos);
+ DependentTypeOfExprType *Canon =
+ DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos);
if (Canon) {
// We already have a "canonical" version of an identical, dependent
// typeof(expr) type. Use that as our canonical type.
- toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr,
- QualType((TypeOfExprType*)Canon, 0));
+ toe = new (*this, TypeAlignment)
+ TypeOfExprType(tofExpr, Kind, QualType((TypeOfExprType *)Canon, 0));
} else {
// Build a new, canonical typeof(expr) type.
- Canon
- = new (*this, TypeAlignment) DependentTypeOfExprType(*this, tofExpr);
+ Canon = new (*this, TypeAlignment)
+ DependentTypeOfExprType(*this, tofExpr, Kind);
DependentTypeOfExprTypes.InsertNode(Canon, InsertPos);
toe = Canon;
}
} else {
QualType Canonical = getCanonicalType(tofExpr->getType());
- toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr, Canonical);
+ toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr, Kind, Canonical);
}
Types.push_back(toe);
return QualType(toe, 0);
@@ -5615,9 +5616,10 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const {
/// memory savings. Since typeof(t) is fairly uncommon, space shouldn't be
/// an issue. This doesn't affect the type checker, since it operates
/// on canonical types (which are always unique).
-QualType ASTContext::getTypeOfType(QualType tofType) const {
+QualType ASTContext::getTypeOfType(QualType tofType, TypeOfKind Kind) const {
QualType Canonical = getCanonicalType(tofType);
- auto *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical);
+ auto *tot =
+ new (*this, TypeAlignment) TypeOfType(tofType, Canonical, Kind);
Types.push_back(tot);
return QualType(tot, 0);
}
@@ -12936,7 +12938,15 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
return Ctx.getTypedefType(CD, Ctx.getQualifiedType(Underlying));
}
case Type::TypeOf:
- return Ctx.getTypeOfType(Ctx.getQualifiedType(Underlying));
+ // The common sugar between two typeof expressions, where one is
+ // potentially a typeof_unqual and the other is not, we unify to the
+ // qualified type as that retains the most information along with the type.
+ // We only return a typeof_unqual type when both types are unqual types.
+ return Ctx.getTypeOfType(Ctx.getQualifiedType(Underlying),
+ cast<TypeOfType>(X)->isUnqual() &&
+ cast<TypeOfType>(Y)->isUnqual()
+ ? TypeOfKind::Unqualified
+ : TypeOfKind::Qualified);
case Type::TypeOfExpr:
return QualType();
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 31a2efd..7ab425d 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1370,16 +1370,17 @@ ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr());
if (!ToExprOrErr)
return ToExprOrErr.takeError();
-
- return Importer.getToContext().getTypeOfExprType(*ToExprOrErr);
+ return Importer.getToContext().getTypeOfExprType(
+ *ToExprOrErr,
+ T->isUnqual() ? TypeOfKind::Unqualified : TypeOfKind::Qualified);
}
ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
- ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+ ExpectedType ToUnderlyingTypeOrErr = import(T->getUnmodifiedType());
if (!ToUnderlyingTypeOrErr)
return ToUnderlyingTypeOrErr.takeError();
-
- return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr);
+ return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr,
+ T->isUnqual() ? TypeOfKind::Unqualified : TypeOfKind::Qualified);
}
ExpectedType ASTNodeImporter::VisitUsingType(const UsingType *T) {
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 7e6055d..8f2ecee 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -974,8 +974,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::TypeOf:
if (!IsStructurallyEquivalent(Context,
- cast<TypeOfType>(T1)->getUnderlyingType(),
- cast<TypeOfType>(T2)->getUnderlyingType()))
+ cast<TypeOfType>(T1)->getUnmodifiedType(),
+ cast<TypeOfType>(T2)->getUnmodifiedType()))
return false;
break;
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 51f8064..de46b40 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -1061,7 +1061,7 @@ public:
VisitType(T);
}
void VisitTypeOfType(const TypeOfType *T) {
- AddQualType(T->getUnderlyingType());
+ AddQualType(T->getUnmodifiedType());
VisitType(T);
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 96028f3..787d88b 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3469,27 +3469,37 @@ QualType MacroQualifiedType::getModifiedType() const {
return Inner;
}
-TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
- : Type(TypeOfExpr, can,
+TypeOfExprType::TypeOfExprType(Expr *E, TypeOfKind Kind, QualType Can)
+ : Type(TypeOfExpr,
+ // We have to protect against 'Can' being invalid through its
+ // default argument.
+ Kind == TypeOfKind::Unqualified && !Can.isNull()
+ ? Can.getAtomicUnqualifiedType()
+ : Can,
toTypeDependence(E->getDependence()) |
(E->getType()->getDependence() &
TypeDependence::VariablyModified)),
- TOExpr(E) {}
+ TOExpr(E) {
+ TypeOfBits.IsUnqual = Kind == TypeOfKind::Unqualified;
+}
bool TypeOfExprType::isSugared() const {
return !TOExpr->isTypeDependent();
}
QualType TypeOfExprType::desugar() const {
- if (isSugared())
- return getUnderlyingExpr()->getType();
-
+ if (isSugared()) {
+ QualType QT = getUnderlyingExpr()->getType();
+ return isUnqual() ? QT.getAtomicUnqualifiedType() : QT;
+ }
return QualType(this, 0);
}
void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
- const ASTContext &Context, Expr *E) {
+ const ASTContext &Context, Expr *E,
+ bool IsUnqual) {
E->Profile(ID, Context, true);
+ ID.AddBoolean(IsUnqual);
}
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 540634c..99566b4 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -521,8 +521,8 @@ void TypeOfTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo>
::initializeLocal(Context, Loc);
- this->getLocalData()->UnderlyingTInfo = Context.getTrivialTypeSourceInfo(
- getUnderlyingType(), Loc);
+ this->getLocalData()->UnmodifiedTInfo =
+ Context.getTrivialTypeSourceInfo(getUnmodifiedType(), Loc);
}
void UnaryTransformTypeLoc::initializeLocal(ASTContext &Context,
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index a7da9fd..c033b35 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1110,7 +1110,7 @@ void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {}
void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
raw_ostream &OS) {
- OS << "typeof ";
+ OS << (T->isUnqual() ? "typeof_unqual " : "typeof ");
if (T->getUnderlyingExpr())
T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
spaceBeforePlaceHolder(OS);
@@ -1120,8 +1120,8 @@ void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
raw_ostream &OS) {}
void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
- OS << "typeof(";
- print(T->getUnderlyingType(), OS, StringRef());
+ OS << (T->isUnqual() ? "typeof_unqual(" : "typeof(");
+ print(T->getUnmodifiedType(), OS, StringRef());
OS << ')';
spaceBeforePlaceHolder(OS);
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 6302741..35432fa 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3287,7 +3287,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
break;
case Type::TypeOf:
- T = cast<TypeOfType>(T)->getUnderlyingType();
+ T = cast<TypeOfType>(T)->getUnmodifiedType();
break;
case Type::Decltype:
T = cast<DecltypeType>(T)->getUnderlyingType();
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 9363827..dfedbf5 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4241,8 +4241,9 @@ void Parser::ParseDeclarationSpecifiers(
continue;
break;
- // GNU typeof support.
+ // C2x/GNU typeof support.
case tok::kw_typeof:
+ case tok::kw_typeof_unqual:
ParseTypeofSpecifier(DS);
continue;
@@ -5252,8 +5253,9 @@ bool Parser::isTypeSpecifierQualifier() {
// GNU attributes support.
case tok::kw___attribute:
- // GNU typeof support.
+ // C2x/GNU typeof support.
case tok::kw_typeof:
+ case tok::kw_typeof_unqual:
// type-specifiers
case tok::kw_short:
@@ -5495,8 +5497,9 @@ bool Parser::isDeclarationSpecifier(
case tok::kw_static_assert:
case tok::kw__Static_assert:
- // GNU typeof support.
+ // C2x/GNU typeof support.
case tok::kw_typeof:
+ case tok::kw_typeof_unqual:
// GNU attributes.
case tok::kw___attribute:
@@ -7543,13 +7546,27 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
/// typeof ( expressions )
/// typeof ( type-name )
/// [GNU/C++] typeof unary-expression
+/// [C2x] typeof-specifier:
+/// typeof '(' typeof-specifier-argument ')'
+/// typeof_unqual '(' typeof-specifier-argument ')'
+///
+/// typeof-specifier-argument:
+/// expression
+/// type-name
///
void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
- assert(Tok.is(tok::kw_typeof) && "Not a typeof specifier");
+ assert(Tok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) &&
+ "Not a typeof specifier");
+
+ bool IsUnqual = Tok.is(tok::kw_typeof_unqual);
+ const IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (getLangOpts().C2x && !II->getName().startswith("__"))
+ Diag(Tok.getLocation(), diag::warn_c2x_compat_typeof_type_specifier)
+ << IsUnqual;
+
Token OpTok = Tok;
SourceLocation StartLoc = ConsumeToken();
-
- const bool hasParens = Tok.is(tok::l_paren);
+ bool HasParens = Tok.is(tok::l_paren);
EnterExpressionEvaluationContext Unevaluated(
Actions, Sema::ExpressionEvaluationContext::Unevaluated,
@@ -7560,7 +7577,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
SourceRange CastRange;
ExprResult Operand = Actions.CorrectDelayedTyposInExpr(
ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange));
- if (hasParens)
+ if (HasParens)
DS.setTypeArgumentRange(CastRange);
if (CastRange.getEnd().isInvalid())
@@ -7578,7 +7595,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
const char *PrevSpec = nullptr;
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
- if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
+ if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualType
+ : DeclSpec::TST_typeofType,
+ StartLoc, PrevSpec,
DiagID, CastTy,
Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
@@ -7601,7 +7620,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
const char *PrevSpec = nullptr;
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
- if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
+ if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualExpr
+ : DeclSpec::TST_typeofExpr,
+ StartLoc, PrevSpec,
DiagID, Operand.get(),
Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 8209aff..89d3b3e 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2288,6 +2288,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
/// typeof ( expressions )
/// typeof ( type-name )
/// [GNU/C++] typeof unary-expression
+/// [C2x] typeof-specifier:
+/// typeof '(' typeof-specifier-argument ')'
+/// typeof_unqual '(' typeof-specifier-argument ')'
+///
+/// typeof-specifier-argument:
+/// expression
+/// type-name
///
/// [OpenCL 1.1 6.11.12] vec_step built-in function:
/// vec_step ( expressions )
@@ -2299,8 +2306,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
ParsedType &CastTy,
SourceRange &CastRange) {
- assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof,
- tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,
+ assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual, tok::kw_sizeof,
+ tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof,
+ tok::kw_vec_step,
tok::kw___builtin_omp_required_simd_align) &&
"Not a typeof/sizeof/alignof/vec_step expression!");
@@ -2336,7 +2344,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
}
isCastExpr = false;
- if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) {
+ if (OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) &&
+ !getLangOpts().CPlusPlus) {
Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo()
<< tok::l_paren;
return ExprError();
@@ -2362,7 +2371,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
return ExprEmpty();
}
- if (getLangOpts().CPlusPlus || OpTok.isNot(tok::kw_typeof)) {
+ if (getLangOpts().CPlusPlus ||
+ !OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual)) {
// GNU typeof in C requires the expression to be parenthesized. Not so for
// sizeof/alignof or in C++. Therefore, the parenthesized expression is
// the start of a unary-expression, but doesn't include any postfix
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 0c4b79d..dc6a1ef 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -384,6 +384,7 @@ bool Declarator::isDeclarationOfFunction() const {
return false;
case TST_decltype:
+ case TST_typeof_unqualExpr:
case TST_typeofExpr:
if (Expr *E = DS.getRepAsExpr())
return E->getType()->isFunctionType();
@@ -392,6 +393,7 @@ bool Declarator::isDeclarationOfFunction() const {
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait:
#include "clang/Basic/TransformTypeTraits.def"
case TST_typename:
+ case TST_typeof_unqualType:
case TST_typeofType: {
QualType QT = DS.getRepAsType().get();
if (QT.isNull())
@@ -573,6 +575,8 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_typename: return "type-name";
case DeclSpec::TST_typeofType:
case DeclSpec::TST_typeofExpr: return "typeof";
+ case DeclSpec::TST_typeof_unqualType:
+ case DeclSpec::TST_typeof_unqualExpr: return "typeof_unqual";
case DeclSpec::TST_auto: return "auto";
case DeclSpec::TST_auto_type: return "__auto_type";
case DeclSpec::TST_decltype: return "(decltype)";
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 77d9516..6c7df68 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -5939,6 +5939,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
switch (DS.getTypeSpecType()) {
case DeclSpec::TST_typename:
case DeclSpec::TST_typeofType:
+ case DeclSpec::TST_typeof_unqualType:
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait:
#include "clang/Basic/TransformTypeTraits.def"
case DeclSpec::TST_atomic: {
@@ -5964,6 +5965,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
}
case DeclSpec::TST_decltype:
+ case DeclSpec::TST_typeof_unqualExpr:
case DeclSpec::TST_typeofExpr: {
Expr *E = DS.getRepAsExpr();
ExprResult Result = S.RebuildExprInCurrentInstantiation(E);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e2040f8..8223bb3d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -6257,7 +6257,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTypeOfExprType(const TypeOfExprType*) {
}
bool UnnamedLocalNoLinkageFinder::VisitTypeOfType(const TypeOfType* T) {
- return Visit(T->getUnderlyingType());
+ return Visit(T->getUnmodifiedType());
}
bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) {
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 9f1942a..36f6333 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5987,8 +5987,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::TypeOf:
if (!OnlyDeduced)
- MarkUsedTemplateParameters(Ctx,
- cast<TypeOfType>(T)->getUnderlyingType(),
+ MarkUsedTemplateParameters(Ctx, cast<TypeOfType>(T)->getUnmodifiedType(),
OnlyDeduced, Depth, Used);
break;
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 69e0c70..4915b48 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -863,6 +863,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
switch (DS.getTypeSpecType()) {
case TST_typename:
+ case TST_typeof_unqualType:
case TST_typeofType:
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait:
#include "clang/Basic/TransformTypeTraits.def"
@@ -873,6 +874,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
break;
}
+ case TST_typeof_unqualExpr:
case TST_typeofExpr:
case TST_decltype:
case TST_bitint:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index aa3160c..3e34408 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1610,6 +1610,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// TypeQuals handled by caller.
break;
}
+ case DeclSpec::TST_typeof_unqualType:
case DeclSpec::TST_typeofType:
// FIXME: Preserve type source info.
Result = S.GetTypeFromParser(DS.getRepAsType());
@@ -1618,13 +1619,20 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
if (const TagType *TT = Result->getAs<TagType>())
S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
// TypeQuals handled by caller.
- Result = Context.getTypeOfType(Result);
+ Result = Context.getTypeOfType(
+ Result, DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualType
+ ? TypeOfKind::Unqualified
+ : TypeOfKind::Qualified);
break;
+ case DeclSpec::TST_typeof_unqualExpr:
case DeclSpec::TST_typeofExpr: {
Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for typeof?");
// TypeQuals handled by caller.
- Result = S.BuildTypeofExprType(E);
+ Result = S.BuildTypeofExprType(E, DS.getTypeSpecType() ==
+ DeclSpec::TST_typeof_unqualExpr
+ ? TypeOfKind::Unqualified
+ : TypeOfKind::Qualified);
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -6103,18 +6111,20 @@ namespace {
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
- assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
+ assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr ||
+ DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualExpr);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
}
void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
- assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
+ assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType ||
+ DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualType);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.setUnderlyingTInfo(TInfo);
+ TL.setUnmodifiedTInfo(TInfo);
}
void VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
@@ -9163,18 +9173,19 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
Keyword, SS.isValid() ? SS.getScopeRep() : nullptr, T, OwnedTagDecl);
}
-QualType Sema::BuildTypeofExprType(Expr *E) {
+QualType Sema::BuildTypeofExprType(Expr *E, TypeOfKind Kind) {
assert(!E->hasPlaceholderType() && "unexpected placeholder");
if (!getLangOpts().CPlusPlus && E->refersToBitField())
- Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield)
+ << (Kind == TypeOfKind::Unqualified ? 3 : 2);
if (!E->isTypeDependent()) {
QualType T = E->getType();
if (const TagType *TT = T->getAs<TagType>())
DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
}
- return Context.getTypeOfExprType(E);
+ return Context.getTypeOfExprType(E, Kind);
}
/// getDecltypeForExpr - Given an expr, will return the decltype for
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index feb31a8..e6109d6 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -963,12 +963,13 @@ public:
///
/// By default, performs semantic analysis when building the typeof type.
/// Subclasses may override this routine to provide different behavior.
- QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc);
+ QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc,
+ TypeOfKind Kind);
/// Build a new typeof(type) type.
///
/// By default, builds a new TypeOfType with the given underlying type.
- QualType RebuildTypeOfType(QualType Underlying);
+ QualType RebuildTypeOfType(QualType Underlying, TypeOfKind Kind);
/// Build a new unary transform type.
QualType RebuildUnaryTransformType(QualType BaseType,
@@ -6199,13 +6200,15 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
return QualType();
QualType Result = TL.getType();
+ bool IsUnqual = Result->getAs<TypeOfExprType>()->isUnqual();
if (getDerived().AlwaysRebuild() ||
E.get() != TL.getUnderlyingExpr()) {
- Result = getDerived().RebuildTypeOfExprType(E.get(), TL.getTypeofLoc());
+ Result = getDerived().RebuildTypeOfExprType(
+ E.get(), TL.getTypeofLoc(),
+ IsUnqual ? TypeOfKind::Unqualified : TypeOfKind::Qualified);
if (Result.isNull())
return QualType();
}
- else E.get();
TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result);
NewTL.setTypeofLoc(TL.getTypeofLoc());
@@ -6218,14 +6221,17 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
template<typename Derived>
QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
TypeOfTypeLoc TL) {
- TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo();
+ TypeSourceInfo* Old_Under_TI = TL.getUnmodifiedTInfo();
TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI);
if (!New_Under_TI)
return QualType();
QualType Result = TL.getType();
+ bool IsUnqual = Result->getAs<TypeOfType>()->isUnqual();
if (getDerived().AlwaysRebuild() || New_Under_TI != Old_Under_TI) {
- Result = getDerived().RebuildTypeOfType(New_Under_TI->getType());
+ Result = getDerived().RebuildTypeOfType(New_Under_TI->getType(),
+ IsUnqual ? TypeOfKind::Unqualified
+ : TypeOfKind::Qualified);
if (Result.isNull())
return QualType();
}
@@ -6234,7 +6240,7 @@ QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
NewTL.setTypeofLoc(TL.getTypeofLoc());
NewTL.setLParenLoc(TL.getLParenLoc());
NewTL.setRParenLoc(TL.getRParenLoc());
- NewTL.setUnderlyingTInfo(New_Under_TI);
+ NewTL.setUnmodifiedTInfo(New_Under_TI);
return Result;
}
@@ -14719,14 +14725,15 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc,
}
template <typename Derived>
-QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E,
- SourceLocation) {
- return SemaRef.BuildTypeofExprType(E);
+QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E, SourceLocation,
+ TypeOfKind Kind) {
+ return SemaRef.BuildTypeofExprType(E, Kind);
}
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
- return SemaRef.Context.getTypeOfType(Underlying);
+QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying,
+ TypeOfKind Kind) {
+ return SemaRef.Context.getTypeOfType(Underlying, Kind);
}
template <typename Derived>
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 5521a9b..7f2bee1 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6662,7 +6662,7 @@ void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
TL.setTypeofLoc(readSourceLocation());
TL.setLParenLoc(readSourceLocation());
TL.setRParenLoc(readSourceLocation());
- TL.setUnderlyingTInfo(GetTypeSourceInfo());
+ TL.setUnmodifiedTInfo(GetTypeSourceInfo());
}
void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 16d0bc7..c9c94d4 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -436,7 +436,7 @@ void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
addSourceLocation(TL.getTypeofLoc());
addSourceLocation(TL.getLParenLoc());
addSourceLocation(TL.getRParenLoc());
- Record.AddTypeSourceInfo(TL.getUnderlyingTInfo());
+ Record.AddTypeSourceInfo(TL.getUnmodifiedTInfo());
}
void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {