aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-07-16 22:05:22 +0000
committerChris Lattner <sabre@nondot.org>2007-07-16 22:05:22 +0000
commita2c7767ce7d8feb10253f4b650826a20f3324c6f (patch)
tree7a6bc8bd0925f0972f9c8176bd3a6a29d419fa9c
parentc80b4eefa221f10871e7fed0ab9dc7d9d3d07dd0 (diff)
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
-rw-r--r--AST/Type.cpp42
-rw-r--r--include/clang/AST/Type.h8
2 files changed, 44 insertions, 6 deletions
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<PointerType>(this))
return PTy;
- // If this is a typedef for a pointer type, strip the typedef off.
- if (const PointerType *PTy = dyn_cast<PointerType>(CanonicalType))
- return PTy;
+
+ // If this is a typedef for a pointer type, strip the typedef off without
+ // losing all typedef information.
+ if (isa<PointerType>(CanonicalType))
+ return cast<PointerType>(cast<TypedefType>(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<VectorType>(this))
return VTy;
- // If this is a typedef for a vector type, strip the typedef off.
- if (const VectorType *VTy = dyn_cast<VectorType>(CanonicalType))
- return VTy;
+
+ // If this is a typedef for a vector type, strip the typedef off without
+ // losing all typedef information.
+ if (isa<VectorType>(CanonicalType))
+ return cast<VectorType>(cast<TypedefType>(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<TypedefType>(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<TypedefType>(CurType);
+ if (TDT == 0)
+ return QualType(CurType.getTypePtr(), TypeQuals);
+ }
+}
bool RecordType::classof(const Type *T) {
if (const TagType *TT = dyn_cast<TagType>(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;