Add experimental support for address space qualified types. Address space
qualifiers use the __attribute__((address_space(id))) syntax.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46691 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/Type.cpp b/AST/Type.cpp
index 6751a23..d3eb003 100644
--- a/AST/Type.cpp
+++ b/AST/Type.cpp
@@ -125,8 +125,12 @@
     return BTy;
 
   // If the canonical form of this type isn't a builtin type, reject it.
-  if (!isa<BuiltinType>(CanonicalType))
+  if (!isa<BuiltinType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<BuiltinType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsBuiltinType();
     return 0;
+  }
 
   // If this is a typedef for a builtin type, strip the typedef off without
   // losing all typedef information.
@@ -137,10 +141,14 @@
   // If this is directly a function type, return it.
   if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
     return FTy;
-  
+
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<FunctionType>(CanonicalType))
+  if (!isa<FunctionType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<FunctionType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsFunctionType();
     return 0;
+  }
   
   // If this is a typedef for a function type, strip the typedef off without
   // losing all typedef information.
@@ -153,8 +161,12 @@
     return PTy;
   
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<PointerType>(CanonicalType))
+  if (!isa<PointerType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<PointerType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsPointerType();
     return 0;
+  }
 
   // If this is a typedef for a pointer type, strip the typedef off without
   // losing all typedef information.
@@ -167,8 +179,12 @@
     return RTy;
   
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<ReferenceType>(CanonicalType))
+  if (!isa<ReferenceType>(CanonicalType)) {    
+    // Look through type qualifiers
+    if (isa<ReferenceType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsReferenceType();
     return 0;
+  }
 
   // If this is a typedef for a reference type, strip the typedef off without
   // losing all typedef information.
@@ -181,8 +197,12 @@
     return ATy;
   
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<ArrayType>(CanonicalType))
+  if (!isa<ArrayType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<ArrayType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsArrayType();
     return 0;
+  }
   
   // If this is a typedef for an array type, strip the typedef off without
   // losing all typedef information.
@@ -193,10 +213,14 @@
   // If this is directly a constant array type, return it.
   if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
     return ATy;
-  
+
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<ConstantArrayType>(CanonicalType))
+  if (!isa<ConstantArrayType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<ConstantArrayType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsConstantArrayType();
     return 0;
+  }
   
   // If this is a typedef for a constant array type, strip the typedef off
   // without losing all typedef information.
@@ -209,8 +233,12 @@
     return ATy;
   
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<VariableArrayType>(CanonicalType))
+  if (!isa<VariableArrayType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<VariableArrayType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsVariableArrayType();
     return 0;
+  }
 
   // If this is a typedef for a variable array type, strip the typedef off
   // without losing all typedef information.
@@ -257,8 +285,12 @@
     return RTy;
   
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<RecordType>(CanonicalType))
+  if (!isa<RecordType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsRecordType();
     return 0;
+  }
 
   // If this is a typedef for a record type, strip the typedef off without
   // losing all typedef information.
@@ -281,6 +313,9 @@
     // losing all typedef information.
     return getDesugaredType()->getAsStructureType();
   }
+  // Look through type qualifiers
+  if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
+    return CanonicalType.getUnqualifiedType()->getAsStructureType();
   return 0;
 }
 
@@ -290,6 +325,7 @@
     if (RT->getDecl()->getKind() == Decl::Union)
       return RT;
   }
+    
   // If the canonical form of this type isn't the right kind, reject it.
   if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
     if (RT->getDecl()->getKind() != Decl::Union)
@@ -299,6 +335,10 @@
     // losing all typedef information.
     return getDesugaredType()->getAsUnionType();
   }
+  
+  // Look through type qualifiers
+  if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
+    return CanonicalType.getUnqualifiedType()->getAsUnionType();
   return 0;
 }
 
@@ -308,8 +348,12 @@
     return CTy;
   
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<ComplexType>(CanonicalType))
+  if (!isa<ComplexType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<ComplexType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsComplexType();
     return 0;
+  }
 
   // If this is a typedef for a complex type, strip the typedef off without
   // losing all typedef information.
@@ -322,8 +366,12 @@
     return VTy;
   
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<VectorType>(CanonicalType))
+  if (!isa<VectorType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<VectorType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsVectorType();
     return 0;
+  }
 
   // If this is a typedef for a vector type, strip the typedef off without
   // losing all typedef information.
@@ -336,8 +384,12 @@
     return VTy;
   
   // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<OCUVectorType>(CanonicalType))
+  if (!isa<OCUVectorType>(CanonicalType)) {  
+    // Look through type qualifiers
+    if (isa<OCUVectorType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsOCUVectorType();
     return 0;
+  }
 
   // If this is a typedef for an ocuvector type, strip the typedef off without
   // losing all typedef information.
@@ -353,6 +405,8 @@
       return true;
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isIntegerType();
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isIntegerType();
   return false;
 }
 
@@ -363,18 +417,24 @@
   if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
     if (TT->getDecl()->getKind() == Decl::Enum)
       return true;
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isIntegralType();
   return false;
 }
 
 bool Type::isEnumeralType() const {
   if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
     return TT->getDecl()->getKind() == Decl::Enum;
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isEnumeralType();
   return false;
 }
 
 bool Type::isBooleanType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() == BuiltinType::Bool;
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isBooleanType();
   return false;
 }
 
@@ -384,6 +444,8 @@
            BT->getKind() == BuiltinType::UChar ||
            BT->getKind() == BuiltinType::Char_S ||
            BT->getKind() == BuiltinType::SChar;
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isCharType();
   return false;
 }
 
@@ -403,6 +465,8 @@
   
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isSignedIntegerType();
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isSignedIntegerType();
   return false;
 }
 
@@ -422,6 +486,8 @@
 
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isUnsignedIntegerType();
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isUnsignedIntegerType();
   return false;
 }
 
@@ -433,6 +499,8 @@
     return CT->getElementType()->isFloatingType();
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isFloatingType();
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isFloatingType();
   return false;
 }
 
@@ -442,6 +510,8 @@
            BT->getKind() <= BuiltinType::LongDouble;
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isRealFloatingType();
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isRealFloatingType();
   return false;
 }
 
@@ -453,6 +523,8 @@
     return TT->getDecl()->getKind() == Decl::Enum;
   if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
     return VT->getElementType()->isRealType();
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isRealType();
   return false;
 }
 
@@ -464,6 +536,8 @@
       // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
       // If a body isn't seen by the time we get here, return false.
       return ED->isDefinition();
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isArithmeticType();
   return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
 }
 
@@ -475,6 +549,8 @@
       return true;
     return false;
   }
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isScalarType();
   return isa<PointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) ||
          isa<ObjCQualifiedIdType>(CanonicalType);
 }
@@ -485,6 +561,8 @@
       return true;
     return false;
   }
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isAggregateType();
   return CanonicalType->getTypeClass() == ConstantArray ||
          CanonicalType->getTypeClass() == VariableArray;
 }
@@ -493,6 +571,8 @@
 /// according to the rules of C99 6.7.5p3.  It is not legal to call this on
 /// incomplete types.
 bool Type::isConstantSizeType(ASTContext &Ctx) const {
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isConstantSizeType(Ctx);
   assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
   // The VAT must have a size, as it is known to be complete.
   return !isa<VariableArrayType>(CanonicalType);
@@ -504,6 +584,8 @@
 bool Type::isIncompleteType() const { 
   switch (CanonicalType->getTypeClass()) { 
   default: return false;
+  case ASQual:
+    return cast<ASQualType>(CanonicalType)->getBaseType()->isIncompleteType();
   case Builtin:
     // Void is the only incomplete builtin type.  Per C99 6.2.5p19, it can never
     // be completed.
@@ -519,6 +601,8 @@
 }
 
 bool Type::isPromotableIntegerType() const {
+  if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+    return ASQT->getBaseType()->isPromotableIntegerType();
   const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
   if (!BT) return false;
   switch (BT->getKind()) {
@@ -685,6 +769,11 @@
   S = "_Complex " + S;
 }
 
+void ASQualType::getAsStringInternal(std::string &S) const {
+  S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S;
+  BaseType->getAsStringInternal(S);
+}
+
 void PointerType::getAsStringInternal(std::string &S) const {
   S = '*' + S;