[cfe-commits] r116409 - in /cfe/trunk: include/clang/AST/Type.h include/clang/Sema/Sema.h lib/AST/Type.cpp
Douglas Gregor
dgregor at apple.com
Wed Oct 13 09:58:14 PDT 2010
Author: dgregor
Date: Wed Oct 13 11:58:14 2010
New Revision: 116409
URL: http://llvm.org/viewvc/llvm-project?rev=116409&view=rev
Log:
Compute whether a type is variably modified as we build the type,
rather than walking the type's structure every time we request this
information. Performance optimization; no functionality change.
Modified:
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/Type.cpp
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=116409&r1=116408&r2=116409&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Oct 13 11:58:14 2010
@@ -793,6 +793,9 @@
/// subclasses can pack their bitfields into the same word.
bool Dependent : 1;
+ /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ bool VariablyModified : 1;
+
/// \brief Whether the linkage of this type is already known.
mutable bool LinkageKnown : 1;
@@ -808,20 +811,25 @@
}
protected:
- /// \brief Compute the linkage of this type.
+ /// \brief Compute the linkage of this type along with the presence of
+ /// any local or unnamed types.
virtual Linkage getLinkageImpl() const;
enum { BitsRemainingInType = 19 };
// silence VC++ warning C4355: 'this' : used in base member initializer list
Type *this_() { return this; }
- Type(TypeClass tc, QualType Canonical, bool dependent)
+ Type(TypeClass tc, QualType Canonical, bool Dependent, bool VariablyModified)
: CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
- TC(tc), Dependent(dependent), LinkageKnown(false),
+ TC(tc), Dependent(Dependent), VariablyModified(VariablyModified),
+ LinkageKnown(false),
CachedLinkage(NoLinkage), FromAST(false) {}
virtual ~Type();
friend class ASTContext;
+ void setDependent(bool D = true) { Dependent = D; }
+ void setVariablyModified(bool VM = true) { VariablyModified = VM; }
+
public:
TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
@@ -854,10 +862,6 @@
/// (C++0x [basic.types]p10)
bool isLiteralType() const;
- /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
- /// types that have a non-constant expression. This does not include "[]".
- bool isVariablyModifiedType() const;
-
/// Helper methods to distinguish type categories. All type predicates
/// operate on the canonical type, ignoring typedefs and qualifiers.
@@ -951,6 +955,10 @@
/// that its definition somehow depends on a template parameter
/// (C++ [temp.dep.type]).
bool isDependentType() const { return Dependent; }
+
+ /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ bool isVariablyModifiedType() const { return VariablyModified; }
+
bool isOverloadableType() const;
/// \brief Determine wither this type is a C++ elaborated-type-specifier.
@@ -1142,7 +1150,8 @@
public:
BuiltinType(Kind K)
- : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)),
+ : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
+ /*VariablyModified=*/false),
TypeKind(K) {}
Kind getKind() const { return TypeKind; }
@@ -1185,7 +1194,8 @@
class ComplexType : public Type, public llvm::FoldingSetNode {
QualType ElementType;
ComplexType(QualType Element, QualType CanonicalPtr) :
- Type(Complex, CanonicalPtr, Element->isDependentType()),
+ Type(Complex, CanonicalPtr, Element->isDependentType(),
+ Element->isVariablyModifiedType()),
ElementType(Element) {
}
friend class ASTContext; // ASTContext creates these.
@@ -1216,7 +1226,9 @@
QualType PointeeType;
PointerType(QualType Pointee, QualType CanonicalPtr) :
- Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) {
+ Type(Pointer, CanonicalPtr, Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType()),
+ PointeeType(Pointee) {
}
friend class ASTContext; // ASTContext creates these.
@@ -1248,7 +1260,8 @@
class BlockPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType; // Block is some kind of pointer type
BlockPointerType(QualType Pointee, QualType CanonicalCls) :
- Type(BlockPointer, CanonicalCls, Pointee->isDependentType()),
+ Type(BlockPointer, CanonicalCls, Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType()),
PointeeType(Pointee) {
}
friend class ASTContext; // ASTContext creates these.
@@ -1302,7 +1315,8 @@
protected:
ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef,
bool SpelledAsLValue) :
- Type(tc, CanonicalRef, Referencee->isDependentType()),
+ Type(tc, CanonicalRef, Referencee->isDependentType(),
+ Referencee->isVariablyModifiedType()),
PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue),
InnerRef(Referencee->isReferenceType()) {
}
@@ -1384,7 +1398,8 @@
MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) :
Type(MemberPointer, CanonicalPtr,
- Cls->isDependentType() || Pointee->isDependentType()),
+ Cls->isDependentType() || Pointee->isDependentType(),
+ Pointee->isVariablyModifiedType()),
PointeeType(Pointee), Class(Cls) {
}
friend class ASTContext; // ASTContext creates these.
@@ -1458,7 +1473,8 @@
// value-dependent,
ArrayType(TypeClass tc, QualType et, QualType can,
ArraySizeModifier sm, unsigned tq)
- : Type(tc, can, et->isDependentType() || tc == DependentSizedArray),
+ : Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
+ (tc == VariableArray || et->isVariablyModifiedType())),
ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {}
friend class ASTContext; // ASTContext creates these.
@@ -1702,7 +1718,8 @@
DependentSizedExtVectorType(ASTContext &Context, QualType ElementType,
QualType can, Expr *SizeExpr, SourceLocation loc)
- : Type (DependentSizedExtVector, can, true),
+ : Type(DependentSizedExtVector, can, /*Dependent=*/true,
+ ElementType->isVariablyModifiedType()),
Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
loc(loc) {}
friend class ASTContext;
@@ -1753,11 +1770,15 @@
VectorType(QualType vecType, unsigned nElements, QualType canonType,
AltiVecSpecific altiVecSpec) :
- Type(Vector, canonType, vecType->isDependentType()),
+ Type(Vector, canonType, vecType->isDependentType(),
+ vecType->isVariablyModifiedType()),
ElementType(vecType), NumElements(nElements), AltiVecSpec(altiVecSpec) {}
+
VectorType(TypeClass tc, QualType vecType, unsigned nElements,
QualType canonType, AltiVecSpecific altiVecSpec)
- : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType),
+ : Type(tc, canonType, vecType->isDependentType(),
+ vecType->isVariablyModifiedType()),
+ ElementType(vecType),
NumElements(nElements), AltiVecSpec(altiVecSpec) {}
friend class ASTContext; // ASTContext creates these.
@@ -1958,8 +1979,8 @@
protected:
FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
unsigned typeQuals, QualType Canonical, bool Dependent,
- const ExtInfo &Info)
- : Type(tc, Canonical, Dependent),
+ bool VariablyModified, const ExtInfo &Info)
+ : Type(tc, Canonical, Dependent, VariablyModified),
SubClassData(SubclassInfo), TypeQuals(typeQuals),
NoReturn(Info.getNoReturn()),
RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {}
@@ -1997,7 +2018,8 @@
FunctionNoProtoType(QualType Result, QualType Canonical,
const ExtInfo &Info)
: FunctionType(FunctionNoProto, Result, false, 0, Canonical,
- /*Dependent=*/false, Info) {}
+ /*Dependent=*/false, Result->isVariablyModifiedType(),
+ Info) {}
friend class ASTContext; // ASTContext creates these.
protected:
@@ -2032,36 +2054,11 @@
/// exception specification, but this specification is not part of the canonical
/// type.
class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
- /// hasAnyDependentType - Determine whether there are any dependent
- /// types within the arguments passed in.
- static bool hasAnyDependentType(const QualType *ArgArray, unsigned numArgs) {
- for (unsigned Idx = 0; Idx < numArgs; ++Idx)
- if (ArgArray[Idx]->isDependentType())
- return true;
-
- return false;
- }
-
FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
bool isVariadic, unsigned typeQuals, bool hasExs,
bool hasAnyExs, const QualType *ExArray,
unsigned numExs, QualType Canonical,
- const ExtInfo &Info)
- : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
- (Result->isDependentType() ||
- hasAnyDependentType(ArgArray, numArgs)),
- Info),
- NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
- AnyExceptionSpec(hasAnyExs) {
- // Fill in the trailing argument array.
- QualType *ArgInfo = reinterpret_cast<QualType*>(this+1);
- for (unsigned i = 0; i != numArgs; ++i)
- ArgInfo[i] = ArgArray[i];
- // Fill in the exception array.
- QualType *Ex = ArgInfo + numArgs;
- for (unsigned i = 0; i != numExs; ++i)
- Ex[i] = ExArray[i];
- }
+ const ExtInfo &Info);
/// NumArgs - The number of arguments this function has, not counting '...'.
unsigned NumArgs : 20;
@@ -2149,7 +2146,7 @@
UnresolvedUsingTypenameDecl *Decl;
UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D)
- : Type(UnresolvedUsing, QualType(), true),
+ : Type(UnresolvedUsing, QualType(), true, false),
Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
public:
@@ -2178,7 +2175,7 @@
TypedefDecl *Decl;
protected:
TypedefType(TypeClass tc, const TypedefDecl *D, QualType can)
- : Type(tc, can, can->isDependentType()),
+ : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType()),
Decl(const_cast<TypedefDecl*>(D)) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
@@ -2251,7 +2248,8 @@
class TypeOfType : public Type {
QualType TOType;
TypeOfType(QualType T, QualType can)
- : Type(TypeOf, can, T->isDependentType()), TOType(T) {
+ : Type(TypeOf, can, T->isDependentType(), T->isVariablyModifiedType()),
+ TOType(T) {
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
friend class ASTContext; // ASTContext creates these.
@@ -2406,11 +2404,13 @@
TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N,
QualType Canon)
- : Type(TemplateTypeParm, Canon, /*Dependent=*/true),
+ : Type(TemplateTypeParm, Canon, /*Dependent=*/true,
+ /*VariablyModified=*/false),
Depth(D), Index(I), ParameterPack(PP), Name(N) { }
TemplateTypeParmType(unsigned D, unsigned I, bool PP)
- : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true),
+ : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true,
+ /*VariablyModified=*/false),
Depth(D), Index(I), ParameterPack(PP), Name(0) { }
friend class ASTContext; // ASTContext creates these
@@ -2455,7 +2455,8 @@
const TemplateTypeParmType *Replaced;
SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
- : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()),
+ : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType(),
+ Canon->isVariablyModifiedType()),
Replaced(Param) { }
friend class ASTContext;
@@ -2629,7 +2630,8 @@
// currently suitable for AST reading, too much
// interdependencies.
InjectedClassNameType(CXXRecordDecl *D, QualType TST)
- : Type(InjectedClassName, QualType(), true),
+ : Type(InjectedClassName, QualType(), /*Dependent=*/true,
+ /*VariablyModified=*/false),
Decl(D), InjectedType(TST) {
assert(isa<TemplateSpecializationType>(TST));
assert(!TST.hasQualifiers());
@@ -2693,8 +2695,9 @@
protected:
TypeWithKeyword(ElaboratedTypeKeyword Keyword, TypeClass tc,
- QualType Canonical, bool dependent)
- : Type(tc, Canonical, dependent), Keyword(Keyword) {}
+ QualType Canonical, bool Dependent, bool VariablyModified)
+ : Type(tc, Canonical, Dependent, VariablyModified),
+ Keyword(Keyword) {}
public:
virtual ~TypeWithKeyword(); // pin vtable to Type.cpp
@@ -2752,7 +2755,8 @@
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
QualType NamedType, QualType CanonType)
: TypeWithKeyword(Keyword, Elaborated, CanonType,
- NamedType->isDependentType()),
+ NamedType->isDependentType(),
+ NamedType->isVariablyModifiedType()),
NNS(NNS), NamedType(NamedType) {
assert(!(Keyword == ETK_None && NNS == 0) &&
"ElaboratedType cannot have elaborated type keyword "
@@ -2812,7 +2816,8 @@
DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, QualType CanonType)
- : TypeWithKeyword(Keyword, DependentName, CanonType, true),
+ : TypeWithKeyword(Keyword, DependentName, CanonType, /*Dependent=*/true,
+ /*VariablyModified=*/false),
NNS(NNS), Name(Name) {
assert(NNS->isDependent() &&
"DependentNameType requires a dependent nested-name-specifier");
@@ -2981,7 +2986,7 @@
enum Nonce_ObjCInterface { Nonce_ObjCInterface };
ObjCObjectType(enum Nonce_ObjCInterface)
- : Type(ObjCInterface, QualType(), false),
+ : Type(ObjCInterface, QualType(), false, false),
NumProtocols(0),
BaseType(QualType(this_(), 0)) {}
@@ -3139,7 +3144,7 @@
QualType PointeeType;
ObjCObjectPointerType(QualType Canonical, QualType Pointee)
- : Type(ObjCObjectPointer, Canonical, false),
+ : Type(ObjCObjectPointer, Canonical, false, false),
PointeeType(Pointee) {}
friend class ASTContext; // ASTContext creates these.
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=116409&r1=116408&r2=116409&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Oct 13 11:58:14 2010
@@ -165,7 +165,8 @@
TypeSourceInfo *DeclInfo;
LocInfoType(QualType ty, TypeSourceInfo *TInfo)
- : Type((TypeClass)LocInfo, ty, ty->isDependentType()), DeclInfo(TInfo) {
+ : Type((TypeClass)LocInfo, ty, ty->isDependentType(),
+ ty->isVariablyModifiedType()), DeclInfo(TInfo) {
assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?");
}
friend class Sema;
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=116409&r1=116408&r2=116409&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Oct 13 11:58:14 2010
@@ -268,42 +268,6 @@
return QualType();
}
-/// isVariablyModifiedType (C99 6.7.5p3) - Return true for variable length
-/// array types and types that contain variable array types in their
-/// declarator
-bool Type::isVariablyModifiedType() const {
- // FIXME: We should really keep a "variably modified" bit in Type, rather
- // than walking the type hierarchy to recompute it.
-
- // A VLA is a variably modified type.
- if (isVariableArrayType())
- return true;
-
- // An array can contain a variably modified type
- if (const Type *T = getArrayElementTypeNoTypeQual())
- return T->isVariablyModifiedType();
-
- // A pointer can point to a variably modified type.
- // Also, C++ references and member pointers can point to a variably modified
- // type, where VLAs appear as an extension to C++, and should be treated
- // correctly.
- if (const PointerType *PT = getAs<PointerType>())
- return PT->getPointeeType()->isVariablyModifiedType();
- if (const ReferenceType *RT = getAs<ReferenceType>())
- return RT->getPointeeType()->isVariablyModifiedType();
- if (const MemberPointerType *PT = getAs<MemberPointerType>())
- return PT->getPointeeType()->isVariablyModifiedType();
-
- // A function can return a variably modified type
- // This one isn't completely obvious, but it follows from the
- // definition in C99 6.7.5p3. Because of this rule, it's
- // illegal to declare a function returning a variably modified type.
- if (const FunctionType *FT = getAs<FunctionType>())
- return FT->getResultType()->isVariablyModifiedType();
-
- return false;
-}
-
const RecordType *Type::getAsStructureType() const {
// If this is directly a structure type, return it.
if (const RecordType *RT = dyn_cast<RecordType>(this)) {
@@ -346,7 +310,7 @@
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols)
- : Type(ObjCObject, Canonical, false),
+ : Type(ObjCObject, Canonical, false, false),
NumProtocols(NumProtocols),
BaseType(Base) {
assert(this->NumProtocols == NumProtocols &&
@@ -913,7 +877,8 @@
NestedNameSpecifier *NNS, const IdentifierInfo *Name,
unsigned NumArgs, const TemplateArgument *Args,
QualType Canon)
- : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true),
+ : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true,
+ false),
NNS(NNS), Name(Name), NumArgs(NumArgs) {
assert(NNS && NNS->isDependent() &&
"DependentTemplateSpecializatonType requires dependent qualifier");
@@ -1026,6 +991,35 @@
}
}
+FunctionProtoType::FunctionProtoType(QualType Result, const QualType *ArgArray,
+ unsigned numArgs, bool isVariadic,
+ unsigned typeQuals, bool hasExs,
+ bool hasAnyExs, const QualType *ExArray,
+ unsigned numExs, QualType Canonical,
+ const ExtInfo &Info)
+ : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
+ Result->isDependentType(),
+ Result->isVariablyModifiedType(),
+ Info),
+ NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
+ AnyExceptionSpec(hasAnyExs)
+{
+ // Fill in the trailing argument array.
+ QualType *ArgInfo = reinterpret_cast<QualType*>(this+1);
+ for (unsigned i = 0; i != numArgs; ++i) {
+ if (ArgArray[i]->isDependentType())
+ setDependent();
+
+ ArgInfo[i] = ArgArray[i];
+ }
+
+ // Fill in the exception array.
+ QualType *Ex = ArgInfo + numArgs;
+ for (unsigned i = 0; i != numExs; ++i)
+ Ex[i] = ExArray[i];
+}
+
+
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys,
unsigned NumArgs, bool isVariadic,
@@ -1087,7 +1081,8 @@
}
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
- : Type(TypeOfExpr, can, E->isTypeDependent()), TOExpr(E) {
+ : Type(TypeOfExpr, can, E->isTypeDependent(),
+ E->getType()->isVariablyModifiedType()), TOExpr(E) {
}
QualType TypeOfExprType::desugar() const {
@@ -1100,7 +1095,8 @@
}
DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can)
- : Type(Decltype, can, E->isTypeDependent()), E(E),
+ : Type(Decltype, can, E->isTypeDependent(),
+ E->getType()->isVariablyModifiedType()), E(E),
UnderlyingType(underlyingType) {
}
@@ -1113,7 +1109,7 @@
}
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
- : Type(TC, can, D->isDependentType()),
+ : Type(TC, can, D->isDependentType(), /*VariablyModified=*/false),
decl(const_cast<TagDecl*>(D)) {}
static TagDecl *getInterestingTagDecl(TagDecl *decl) {
@@ -1213,16 +1209,25 @@
unsigned NumArgs, QualType Canon)
: Type(TemplateSpecialization,
Canon.isNull()? QualType(this, 0) : Canon,
- T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)),
- Template(T), NumArgs(NumArgs) {
+ T.isDependent(), false),
+ Template(T), NumArgs(NumArgs)
+{
assert((!Canon.isNull() ||
T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) &&
"No canonical type for non-dependent class template specialization");
TemplateArgument *TemplateArgs
= reinterpret_cast<TemplateArgument *>(this + 1);
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ // Update dependent and variably-modified bits.
+ if (isDependent(Args[Arg]))
+ setDependent();
+ if (Args[Arg].getKind() == TemplateArgument::Type &&
+ Args[Arg].getAsType()->isVariablyModifiedType())
+ setVariablyModified();
+
new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
+ }
}
void
More information about the cfe-commits
mailing list