From: Chris Lattner Date: Mon, 16 Jul 2007 22:05:22 +0000 (+0000) Subject: In the final step for preserving typedef info better in the AST, upgrade X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a2c7767ce7d8feb10253f4b650826a20f3324c6f;p=clang In the final step for preserving typedef info better in the AST, upgrade isPointerType and isVectorType to only look through a single level of typedef when one is present. For this invalid code: typedef float float4 __attribute__((vector_size(16))); typedef int int4 __attribute__((vector_size(16))); typedef int4* int4p; void test(float4 a, int4p result, int i) { result[i] = a; } we now get: t.c:5:15: error: incompatible types assigning 'float4' to 'int4' result[i] = a; ~~~~~~~~~ ^ ~ instead of: t.c:5:15: error: incompatible types assigning 'float4' to 'int __attribute__((vector_size(16)))' result[i] = a; ~~~~~~~~~ ^ ~ The rest of the type predicates should be upgraded to do the same thing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39932 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Type.cpp b/AST/Type.cpp index 0bc058f742..7b999faa66 100644 --- a/AST/Type.cpp +++ b/AST/Type.cpp @@ -64,9 +64,11 @@ const PointerType *Type::isPointerType() const { // If this is directly a pointer type, return it. if (const PointerType *PTy = dyn_cast(this)) return PTy; - // If this is a typedef for a pointer type, strip the typedef off. - if (const PointerType *PTy = dyn_cast(CanonicalType)) - return PTy; + + // If this is a typedef for a pointer type, strip the typedef off without + // losing all typedef information. + if (isa(CanonicalType)) + return cast(cast(this)->LookThroughTypedefs()); return 0; } @@ -102,9 +104,12 @@ const VectorType *Type::isVectorType() const { // Are we directly a vector type? if (const VectorType *VTy = dyn_cast(this)) return VTy; - // If this is a typedef for a vector type, strip the typedef off. - if (const VectorType *VTy = dyn_cast(CanonicalType)) - return VTy; + + // If this is a typedef for a vector type, strip the typedef off without + // losing all typedef information. + if (isa(CanonicalType)) + return cast(cast(this)->LookThroughTypedefs()); + return 0; } @@ -423,6 +428,31 @@ void FunctionTypeProto::Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getResultType(), ArgInfo, NumArgs, isVariadic()); } +/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to +/// potentially looking through *all* consequtive typedefs. This returns the +/// sum of the type qualifiers, so if you have: +/// typedef const int A; +/// typedef volatile A B; +/// looking through the typedefs for B will give you "const volatile A". +/// +QualType TypedefType::LookThroughTypedefs() const { + // Usually, there is only a single level of typedefs, be fast in that case. + QualType FirstType = getDecl()->getUnderlyingType(); + if (!isa(FirstType)) + return FirstType; + + // Otherwise, do the fully general loop. + unsigned TypeQuals = 0; + const TypedefType *TDT = this; + while (1) { + QualType CurType = TDT->getDecl()->getUnderlyingType(); + TypeQuals |= CurType.getQualifiers(); + + TDT = dyn_cast(CurType); + if (TDT == 0) + return QualType(CurType.getTypePtr(), TypeQuals); + } +} bool RecordType::classof(const Type *T) { if (const TagType *TT = dyn_cast(T)) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index ecce34c64e..83d79df4a5 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -585,6 +585,14 @@ class TypedefType : public Type { public: TypedefDecl *getDecl() const { return Decl; } + + /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to + /// potentially looking through *all* consequtive typedefs. This returns the + /// sum of the type qualifiers, so if you have: + /// typedef const int A; + /// typedef volatile A B; + /// looking through the typedefs for B will give you "const volatile A". + QualType LookThroughTypedefs() const; virtual void getAsStringInternal(std::string &InnerString) const;