summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/ASTContext.h9
-rw-r--r--clang/include/clang/AST/Decl.h6
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h8
-rw-r--r--clang/include/clang/AST/Type.h38
-rw-r--r--clang/include/clang/AST/TypeLoc.h34
-rw-r--r--clang/include/clang/AST/TypeNodes.def1
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--clang/lib/AST/ASTContext.cpp60
-rw-r--r--clang/lib/AST/ASTImporter.cpp7
-rw-r--r--clang/lib/AST/Decl.cpp8
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp1
-rw-r--r--clang/lib/AST/TypePrinter.cpp9
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp4
-rw-r--r--clang/lib/Sema/SemaExpr.cpp2
-rw-r--r--clang/lib/Sema/SemaType.cpp7
-rw-r--r--clang/lib/Sema/TreeTransform.h16
-rw-r--r--clang/lib/Serialization/ASTReader.cpp15
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp8
-rw-r--r--clang/test/Index/print-type.c2
-rw-r--r--clang/test/Sema/function.c10
-rw-r--r--clang/test/SemaCXX/function-type-qual.cpp8
-rw-r--r--clang/tools/libclang/CIndex.cpp4
-rw-r--r--clang/tools/libclang/RecursiveASTVisitor.h8
24 files changed, 246 insertions, 27 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index ebbf6c99e66..ae7a8f14d44 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -82,6 +82,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
mutable llvm::FoldingSet<ComplexType> ComplexTypes;
mutable llvm::FoldingSet<PointerType> PointerTypes;
+ mutable llvm::FoldingSet<DecayedType> DecayedTypes;
mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
@@ -889,6 +890,14 @@ public:
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
}
+ /// \brief Return the uniqued reference to the decayed version of the given
+ /// type. Can only be called on array and function types which decay to
+ /// pointer types.
+ QualType getDecayedType(QualType T) const;
+ CanQualType getDecayedType(CanQualType T) const {
+ return CanQualType::CreateUnsafe(getDecayedType((QualType) T));
+ }
+
/// \brief Return the uniqued reference to the atomic type for the specified
/// type.
QualType getAtomicType(QualType T) const;
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 5d94278e99d..25e37099f88 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -1337,11 +1337,7 @@ public:
ParmVarDeclBits.HasInheritedDefaultArg = I;
}
- QualType getOriginalType() const {
- if (getTypeSourceInfo())
- return getTypeSourceInfo()->getType();
- return getType();
- }
+ QualType getOriginalType() const;
/// \brief Determine whether this parameter is actually a function
/// parameter pack.
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 1072b97a14a..df71bffe850 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -847,6 +847,10 @@ DEF_TRAVERSE_TYPE(MemberPointerType, {
TRY_TO(TraverseType(T->getPointeeType()));
})
+DEF_TRAVERSE_TYPE(DecayedType, {
+ TRY_TO(TraverseType(T->getOriginalType()));
+ })
+
DEF_TRAVERSE_TYPE(ConstantArrayType, {
TRY_TO(TraverseType(T->getElementType()));
})
@@ -1053,6 +1057,10 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, {
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
+DEF_TRAVERSE_TYPELOC(DecayedType, {
+ TRY_TO(TraverseTypeLoc(TL.getOriginalLoc()));
+ })
+
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
// This isn't available for ArrayType, but is for the ArrayTypeLoc.
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index bd2e18878ee..2566268a626 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1991,6 +1991,44 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
};
+/// \brief Represents a pointer type decayed from an array or function type.
+class DecayedType : public Type, public llvm::FoldingSetNode {
+ QualType OriginalType;
+ QualType DecayedPointer;
+
+ DecayedType(QualType OriginalType, QualType DecayedPointer,
+ QualType CanonicalPtr)
+ : Type(Decayed, CanonicalPtr, OriginalType->isDependentType(),
+ OriginalType->isInstantiationDependentType(),
+ OriginalType->isVariablyModifiedType(),
+ OriginalType->containsUnexpandedParameterPack()),
+ OriginalType(OriginalType), DecayedPointer(DecayedPointer) {
+ assert(isa<PointerType>(DecayedPointer));
+ }
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ QualType getDecayedType() const { return DecayedPointer; }
+ QualType getOriginalType() const { return OriginalType; }
+
+ QualType getPointeeType() const {
+ return cast<PointerType>(DecayedPointer)->getPointeeType();
+ }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return DecayedPointer; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, OriginalType);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType OriginalType) {
+ ID.AddPointer(OriginalType.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Decayed; }
+};
+
/// BlockPointerType - pointer to a block type.
/// This type is to represent types syntactically represented as
/// "void (^)(int)", etc. Pointee is required to always be a function type.
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 1eb8835f4d6..a028a6f35c8 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -974,6 +974,40 @@ inline TypeLoc TypeLoc::IgnoreParens() const {
return *this;
}
+
+struct DecayedLocInfo { }; // Nothing.
+
+/// \brief Wrapper for source info for pointers decayed from arrays and
+/// funcitons.
+class DecayedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, DecayedTypeLoc,
+ DecayedType, DecayedLocInfo> {
+public:
+ TypeLoc getOriginalLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ // do nothing
+ }
+
+ QualType getInnerType() const {
+ // The inner type is the undecayed type, since that's what we have source
+ // location information for.
+ return getTypePtr()->getOriginalType();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange();
+ }
+
+ unsigned getLocalDataSize() const {
+ // sizeof(DecayedLocInfo) is 1, but we don't need its address to be unique
+ // anyway. TypeLocBuilder can't handle data sizes of 1.
+ return 0; // No data.
+ }
+};
+
+
struct PointerLikeLocInfo {
SourceLocation StarLoc;
};
diff --git a/clang/include/clang/AST/TypeNodes.def b/clang/include/clang/AST/TypeNodes.def
index 840e07d94a0..a29ae231e94 100644
--- a/clang/include/clang/AST/TypeNodes.def
+++ b/clang/include/clang/AST/TypeNodes.def
@@ -81,6 +81,7 @@ TYPE(FunctionNoProto, FunctionType)
DEPENDENT_TYPE(UnresolvedUsing, Type)
NON_CANONICAL_TYPE(Paren, Type)
NON_CANONICAL_TYPE(Typedef, Type)
+NON_CANONICAL_TYPE(Decayed, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 651b4a9df2d..ec05cc216bf 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -836,7 +836,9 @@ namespace clang {
/// \brief A UnaryTransformType record.
TYPE_UNARY_TRANSFORM = 39,
/// \brief An AtomicType record.
- TYPE_ATOMIC = 40
+ TYPE_ATOMIC = 40,
+ /// \brief A DecayedType record.
+ TYPE_DECAYED = 41
};
/// \brief The type IDs for special types constructed by semantic
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 70c933e7521..91059400761 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1615,6 +1615,8 @@ ASTContext::getTypeInfoImpl(const Type *T) const {
}
case Type::ObjCObject:
return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr());
+ case Type::Decayed:
+ return getTypeInfo(cast<DecayedType>(T)->getDecayedType().getTypePtr());
case Type::ObjCInterface: {
const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
@@ -2167,6 +2169,45 @@ QualType ASTContext::getPointerType(QualType T) const {
return QualType(New, 0);
}
+QualType ASTContext::getDecayedType(QualType T) const {
+ assert((T->isArrayType() || T->isFunctionType()) && "T does not decay");
+
+ llvm::FoldingSetNodeID ID;
+ DecayedType::Profile(ID, T);
+ void *InsertPos = 0;
+ if (DecayedType *DT = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(DT, 0);
+
+ QualType Decayed;
+
+ // C99 6.7.5.3p7:
+ // A declaration of a parameter as "array of type" shall be
+ // adjusted to "qualified pointer to type", where the type
+ // qualifiers (if any) are those specified within the [ and ] of
+ // the array type derivation.
+ if (T->isArrayType())
+ Decayed = getArrayDecayedType(T);
+
+ // C99 6.7.5.3p8:
+ // A declaration of a parameter as "function returning type"
+ // shall be adjusted to "pointer to function returning type", as
+ // in 6.3.2.1.
+ if (T->isFunctionType())
+ Decayed = getPointerType(T);
+
+ QualType Canonical = getCanonicalType(Decayed);
+
+ // Get the new insert position for the node we care about.
+ DecayedType *NewIP = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
+
+ DecayedType *New =
+ new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical);
+ Types.push_back(New);
+ DecayedTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
/// getBlockPointerType - Return the uniqued reference to the type for
/// a pointer to the specified block.
QualType ASTContext::getBlockPointerType(QualType T) const {
@@ -4154,22 +4195,9 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
}
QualType ASTContext::getAdjustedParameterType(QualType T) const {
- // C99 6.7.5.3p7:
- // A declaration of a parameter as "array of type" shall be
- // adjusted to "qualified pointer to type", where the type
- // qualifiers (if any) are those specified within the [ and ] of
- // the array type derivation.
- if (T->isArrayType())
- return getArrayDecayedType(T);
-
- // C99 6.7.5.3p8:
- // A declaration of a parameter as "function returning type"
- // shall be adjusted to "pointer to function returning type", as
- // in 6.3.2.1.
- if (T->isFunctionType())
- return getPointerType(T);
-
- return T;
+ if (T->isArrayType() || T->isFunctionType())
+ return getDecayedType(T);
+ return T;
}
QualType ASTContext::getSignatureParameterType(QualType T) const {
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 41a67af64d6..84904580162 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -400,6 +400,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
break;
+ case Type::Decayed:
+ if (!IsStructurallyEquivalent(Context,
+ cast<DecayedType>(T1)->getPointeeType(),
+ cast<DecayedType>(T2)->getPointeeType()))
+ return false;
+ break;
+
case Type::Pointer:
if (!IsStructurallyEquivalent(Context,
cast<PointerType>(T1)->getPointeeType(),
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index c799161e9b7..9702d032453 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1995,6 +1995,14 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
S, DefArg);
}
+QualType ParmVarDecl::getOriginalType() const {
+ TypeSourceInfo *TSI = getTypeSourceInfo();
+ QualType T = TSI ? TSI->getType() : getType();
+ if (const DecayedType *DT = dyn_cast<DecayedType>(T))
+ return DT->getOriginalType();
+ return T;
+}
+
ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl));
return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(),
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 065465aa59e..7102bf349b2 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -828,6 +828,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
switch (type->getTypeClass()) {
case Type::Builtin:
case Type::Complex:
+ case Type::Decayed:
case Type::Pointer:
case Type::BlockPointer:
case Type::LValueReference:
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 2c439128f2d..d19c6a94508 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -201,6 +201,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
NeedARCStrongQualifier = true;
// Fall through
+ case Type::Decayed:
case Type::Pointer:
case Type::BlockPointer:
case Type::LValueReference:
@@ -468,6 +469,14 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
printAfter(T->getElementType(), OS);
}
+void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) {
+ // Print as though it's a pointer.
+ printBefore(T->getDecayedType(), OS);
+}
+void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) {
+ printAfter(T->getDecayedType(), OS);
+}
+
void TypePrinter::printDependentSizedArrayBefore(
const DependentSizedArrayType *T,
raw_ostream &OS) {
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index e38327a9270..9d2b23ed185 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2069,6 +2069,10 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit,
return CreateType(cast<ComplexType>(Ty));
case Type::Pointer:
return CreateType(cast<PointerType>(Ty), Unit);
+ case Type::Decayed:
+ // Decayed types are just pointers in LLVM and DWARF.
+ return CreateType(
+ cast<PointerType>(cast<DecayedType>(Ty)->getDecayedType()), Unit);
case Type::BlockPointer:
return CreateType(cast<BlockPointerType>(Ty), Unit);
case Type::Typedef:
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 297fc655e44..c6b498cd586 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1273,6 +1273,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::ObjCObjectPointer:
llvm_unreachable("type class is never variably-modified!");
+ case Type::Decayed:
+ type = cast<DecayedType>(ty)->getPointeeType();
+ break;
+
case Type::Pointer:
type = cast<PointerType>(ty)->getPointeeType();
break;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 27e8962f71b..1d2f39c0da3 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4021,6 +4021,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc();
+ if (DecayedTypeLoc DTL = TL.getAs<DecayedTypeLoc>())
+ TL = DTL.getOriginalLoc();
if (ArrayTypeLoc ATL = TL.getAs<ArrayTypeLoc>())
S.Diag(PVD->getLocation(), diag::note_callee_static_array)
<< ATL.getLocalSourceRange();
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index f5a28966f86..e1f0739aea7 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2844,10 +2844,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType ArgTy = Param->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
- // Adjust the parameter type.
- assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&
- "Unadjusted type?");
-
// Look for 'void'. void is allowed only as a single argument to a
// function with no other parameters (C99 6.7.5.3p10). We record
// int(void) as a FunctionProtoType with an empty argument list.
@@ -3577,6 +3573,9 @@ namespace {
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
llvm_unreachable("qualified type locs not expected here!");
}
+ void VisitDecayedTypeLoc(DecayedTypeLoc TL) {
+ llvm_unreachable("decayed type locs not expected here!");
+ }
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, Chunk.getAttrs());
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 86624c580e5..9fbbe2cf1d5 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3586,6 +3586,22 @@ QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
}
template<typename Derived>
+QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB,
+ DecayedTypeLoc TL) {
+ QualType OriginalType = getDerived().TransformType(TLB, TL.getOriginalLoc());
+ if (OriginalType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ OriginalType != TL.getOriginalLoc().getType())
+ Result = SemaRef.Context.getDecayedType(OriginalType);
+ TLB.push<DecayedTypeLoc>(Result);
+ // Nothing to set for DecayedTypeLoc.
+ return Result;
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
PointerTypeLoc TL) {
QualType PointeeType
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f33e0e14cf6..052bef9e5be 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4531,6 +4531,18 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
return Context.getPointerType(PointeeType);
}
+ case TYPE_DECAYED: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of decayed type");
+ return QualType();
+ }
+ QualType OriginalType = readType(*Loc.F, Record, Idx);
+ QualType DT = Context.getAdjustedParameterType(OriginalType);
+ if (!isa<DecayedType>(DT))
+ Error("Decayed type does not decay");
+ return DT;
+ }
+
case TYPE_BLOCK_POINTER: {
if (Record.size() != 1) {
Error("Incorrect encoding of block pointer type");
@@ -4977,6 +4989,9 @@ void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
TL.setStarLoc(ReadSourceLocation(Record, Idx));
}
+void TypeLocReader::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
+ // nothing to do
+}
void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
TL.setCaretLoc(ReadSourceLocation(Record, Idx));
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 3654ec27f40..4a4128b4cfd 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -108,6 +108,11 @@ void ASTTypeWriter::VisitPointerType(const PointerType *T) {
Code = TYPE_POINTER;
}
+void ASTTypeWriter::VisitDecayedType(const DecayedType *T) {
+ Writer.AddTypeRef(T->getOriginalType(), Record);
+ Code = TYPE_DECAYED;
+}
+
void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
Code = TYPE_BLOCK_POINTER;
@@ -447,6 +452,9 @@ void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
Writer.AddSourceLocation(TL.getStarLoc(), Record);
}
+void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
+ // nothing to do
+}
void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
Writer.AddSourceLocation(TL.getCaretLoc(), Record);
}
diff --git a/clang/test/Index/print-type.c b/clang/test/Index/print-type.c
index 4805f59f3fe..03f0b7c89ad 100644
--- a/clang/test/Index/print-type.c
+++ b/clang/test/Index/print-type.c
@@ -35,7 +35,7 @@ typedef int __attribute__((vector_size(16))) int4_t;
// CHECK: DeclRefExpr=p:3:13 [type=int *] [typekind=Pointer] [isPOD=1]
// CHECK: DeclRefExpr=z:3:33 [type=FooType] [typekind=Typedef] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: ArraySubscriptExpr= [type=int] [typekind=Int] [isPOD=1]
-// CHECK: DeclRefExpr=arr:3:40 [type=int *] [typekind=Pointer] [isPOD=1]
+// CHECK: UnexposedExpr=arr:3:40 [type=int *] [typekind=Unexposed] [canonicaltype=int *] [canonicaltypekind=Pointer] [isPOD=1]
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
// CHECK: TypedefDecl=OtherType:8:16 (Definition) [type=OtherType] [typekind=Typedef] [canonicaltype=double] [canonicaltypekind=Double] [isPOD=1]
// CHECK: TypedefDecl=ArrayType:9:13 (Definition) [type=ArrayType] [typekind=Typedef] [canonicaltype=int [5]] [canonicaltypekind=ConstantArray] [isPOD=1]
diff --git a/clang/test/Sema/function.c b/clang/test/Sema/function.c
index bbf81a56cbb..81d303c27f6 100644
--- a/clang/test/Sema/function.c
+++ b/clang/test/Sema/function.c
@@ -103,3 +103,13 @@ int func_e(int x) {
}
return x + 3;
}
+
+void decays(int a[3][3]); // expected-note {{passing argument to parameter 'a' here}}
+void no_decay(int (*a)[3]); // expected-note {{passing argument to parameter 'a' here}}
+
+void t22(int *ptr, int (*array)[3]) {
+ decays(ptr); // expected-warning {{incompatible pointer types passing 'int *' to parameter of type 'int (*)[3]'}}
+ no_decay(ptr); // expected-warning {{incompatible pointer types passing 'int *' to parameter of type 'int (*)[3]'}}
+ decays(array);
+ no_decay(array);
+}
diff --git a/clang/test/SemaCXX/function-type-qual.cpp b/clang/test/SemaCXX/function-type-qual.cpp
index ccb57472925..613ac9b200f 100644
--- a/clang/test/SemaCXX/function-type-qual.cpp
+++ b/clang/test/SemaCXX/function-type-qual.cpp
@@ -29,3 +29,11 @@ cfn C::*mpg;
// Don't crash!
void (PR14171)() const; // expected-error {{non-member function cannot have 'const' qualifier}}
+
+// Test template instantiation of decayed array types. Not really related to
+// type quals.
+template <typename T> void arrayDecay(const T a[]) { }
+void instantiateArrayDecay() {
+ int a[1];
+ arrayDecay(a);
+}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 83b251968bc..09bb0eba8f5 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1546,6 +1546,10 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
return false;
}
+bool CursorVisitor::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
+ return Visit(TL.getOriginalLoc());
+}
+
bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
// Visit the template name.
diff --git a/clang/tools/libclang/RecursiveASTVisitor.h b/clang/tools/libclang/RecursiveASTVisitor.h
index 0958d52e79c..17d70d6212e 100644
--- a/clang/tools/libclang/RecursiveASTVisitor.h
+++ b/clang/tools/libclang/RecursiveASTVisitor.h
@@ -786,6 +786,10 @@ DEF_TRAVERSE_TYPE(MemberPointerType, {
TRY_TO(TraverseType(T->getPointeeType()));
})
+DEF_TRAVERSE_TYPE(DecayedType, {
+ TRY_TO(TraverseType(T->getOriginalType()));
+ })
+
DEF_TRAVERSE_TYPE(ConstantArrayType, {
TRY_TO(TraverseType(T->getElementType()));
})
@@ -992,6 +996,10 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, {
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
+DEF_TRAVERSE_TYPELOC(DecayedType, {
+ TRY_TO(TraverseTypeLoc(TL.getOriginalLoc()));
+ })
+
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
// This isn't available for ArrayType, but is for the ArrayTypeLoc.
OpenPOWER on IntegriCloud