summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp124
1 files changed, 100 insertions, 24 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 8278691..d1a74be 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -81,9 +81,12 @@ static void ProcessDelayedFnAttrs(Sema &S, QualType &Type,
DelayedAttributeSet &Attrs) {
for (DelayedAttributeSet::iterator I = Attrs.begin(),
E = Attrs.end(); I != E; ++I)
- if (ProcessFnAttr(S, Type, *I->first))
+ if (ProcessFnAttr(S, Type, *I->first)) {
S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
<< I->first->getName() << I->second;
+ // Avoid any further processing of this attribute.
+ I->first->setInvalid();
+ }
Attrs.clear();
}
@@ -92,6 +95,8 @@ static void DiagnoseDelayedFnAttrs(Sema &S, DelayedAttributeSet &Attrs) {
E = Attrs.end(); I != E; ++I) {
S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
<< I->first->getName() << I->second;
+ // Avoid any further processing of this attribute.
+ I->first->setInvalid();
}
Attrs.clear();
}
@@ -280,6 +285,7 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
if (TheSema.getLangOptions().CPlusPlus) {
TagDecl::TagKind Tag
= TagDecl::getTagKindForTypeSpec(DS.getTypeSpecType());
+ Result = TheSema.getQualifiedNameType(DS.getTypeSpecScope(), Result);
Result = Context.getElaboratedType(Result, Tag);
}
@@ -498,6 +504,8 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,
Qs.removeRestrict();
}
+ assert(!T->isObjCInterfaceType() && "Should build ObjCObjectPointerType");
+
// Build the pointer type.
return Context.getQualifiedType(Context.getPointerType(T), Qs);
}
@@ -604,15 +612,31 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
SourceRange Brackets, DeclarationName Entity) {
SourceLocation Loc = Brackets.getBegin();
- // C99 6.7.5.2p1: If the element type is an incomplete or function type,
- // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
- // Not in C++, though. There we only dislike void.
if (getLangOptions().CPlusPlus) {
+ // C++ [dcl.array]p1:
+ // T is called the array element type; this type shall not be a reference
+ // type, the (possibly cv-qualified) type void, a function type or an
+ // abstract class type.
+ //
+ // Note: function types are handled in the common path with C.
+ if (T->isReferenceType()) {
+ Diag(Loc, diag::err_illegal_decl_array_of_references)
+ << getPrintableNameForEntity(Entity) << T;
+ return QualType();
+ }
+
if (T->isVoidType()) {
Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
return QualType();
}
+
+ if (RequireNonAbstractType(Brackets.getBegin(), T,
+ diag::err_array_of_abstract_type))
+ return QualType();
+
} else {
+ // C99 6.7.5.2p1: If the element type is an incomplete or function type,
+ // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
if (RequireCompleteType(Loc, T,
diag::err_illegal_decl_array_incomplete_type))
return QualType();
@@ -624,13 +648,6 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return QualType();
}
- // C++ 8.3.2p4: There shall be no ... arrays of references ...
- if (T->isReferenceType()) {
- Diag(Loc, diag::err_illegal_decl_array_of_references)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
-
if (Context.getCanonicalType(T) == Context.UndeducedAutoTy) {
Diag(Loc, diag::err_illegal_decl_array_of_auto)
<< getPrintableNameForEntity(Entity);
@@ -922,7 +939,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// Determine the type of the declarator. Not all forms of declarator
// have a type.
QualType T;
-
+ TypeSourceInfo *ReturnTypeInfo = 0;
+
llvm::SmallVector<DelayedAttribute,4> FnAttrsFromDeclSpec;
switch (D.getName().getKind()) {
@@ -948,12 +966,17 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// Constructors and destructors don't have return types. Use
// "void" instead.
T = Context.VoidTy;
+
+ if (TInfo)
+ ReturnTypeInfo = Context.getTrivialTypeSourceInfo(T,
+ D.getName().StartLocation);
break;
case UnqualifiedId::IK_ConversionFunctionId:
// The result type of a conversion function is the type that it
// converts to.
- T = GetTypeFromParser(D.getName().ConversionFunctionId);
+ T = GetTypeFromParser(D.getName().ConversionFunctionId,
+ TInfo? &ReturnTypeInfo : 0);
break;
}
@@ -1036,7 +1059,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (getLangOptions().ObjC1 && T->isObjCInterfaceType()) {
const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>();
T = Context.getObjCObjectPointerType(T,
- (ObjCProtocolDecl **)OIT->qual_begin(),
+ const_cast<ObjCProtocolDecl **>(
+ OIT->qual_begin()),
OIT->getNumProtocols(),
DeclType.Ptr.TypeQuals);
break;
@@ -1253,8 +1277,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
// The scope spec must refer to a class, or be dependent.
QualType ClsType;
- if (isDependentScopeSpecifier(DeclType.Mem.Scope())
- || dyn_cast_or_null<CXXRecordDecl>(
+ if (DeclType.Mem.Scope().isInvalid()) {
+ // Avoid emitting extra errors if we already errored on the scope.
+ D.setInvalidType(true);
+ } else if (isDependentScopeSpecifier(DeclType.Mem.Scope())
+ || dyn_cast_or_null<CXXRecordDecl>(
computeDeclContext(DeclType.Mem.Scope()))) {
NestedNameSpecifier *NNS
= (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
@@ -1353,7 +1380,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (D.isInvalidType())
*TInfo = 0;
else
- *TInfo = GetTypeSourceInfoForDeclarator(D, T);
+ *TInfo = GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo);
}
return T;
@@ -1538,8 +1565,14 @@ namespace {
/// \brief Create and instantiate a TypeSourceInfo with type source information.
///
/// \param T QualType referring to the type as written in source code.
+///
+/// \param ReturnTypeInfo For declarators whose return type does not show
+/// up in the normal place in the declaration specifiers (such as a C++
+/// conversion function), this pointer will refer to a type source information
+/// for that return type.
TypeSourceInfo *
-Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T) {
+Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
+ TypeSourceInfo *ReturnTypeInfo) {
TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
@@ -1549,7 +1582,18 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T) {
}
TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);
-
+
+ // We have source information for the return type that was not in the
+ // declaration specifiers; copy that information into the current type
+ // location so that it will be retained. This occurs, for example, with
+ // a C++ conversion function, where the return type occurs within the
+ // declarator-id rather than in the declaration specifiers.
+ if (ReturnTypeInfo && D.getDeclSpec().getTypeSpecType() == TST_unspecified) {
+ TypeLoc TL = ReturnTypeInfo->getTypeLoc();
+ assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
+ memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
+ }
+
return TInfo;
}
@@ -1648,12 +1692,14 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
// for two or more different address spaces."
if (Type.getAddressSpace()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
+ Attr.setInvalid();
return;
}
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
return;
}
Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
@@ -1661,6 +1707,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
if (!ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
<< ASArgExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
@@ -1669,6 +1716,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
if (addrSpace.isNegative()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
<< ASArgExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
addrSpace.setIsSigned(false);
@@ -1678,6 +1726,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
if (addrSpace > max) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
<< Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
@@ -1691,6 +1740,7 @@ static void HandleObjCGCTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S) {
if (Type.getObjCGCAttr() != Qualifiers::GCNone) {
S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc);
+ Attr.setInvalid();
return;
}
@@ -1698,11 +1748,13 @@ static void HandleObjCGCTypeAttribute(QualType &Type,
if (!Attr.getParameterName()) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
<< "objc_gc" << 1;
+ Attr.setInvalid();
return;
}
Qualifiers::GC GCAttr;
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
return;
}
if (Attr.getParameterName()->isStr("weak"))
@@ -1712,6 +1764,7 @@ static void HandleObjCGCTypeAttribute(QualType &Type,
else {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
<< "objc_gc" << Attr.getParameterName();
+ Attr.setInvalid();
return;
}
@@ -1725,6 +1778,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
// Complain immediately if the arg count is wrong.
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ Attr.setInvalid();
return false;
}
@@ -1766,6 +1820,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
// Otherwise, a calling convention.
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ Attr.setInvalid();
return false;
}
@@ -1788,13 +1843,17 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
CallingConv CCOld = Fn->getCallConv();
if (S.Context.getCanonicalCallConv(CC) ==
- S.Context.getCanonicalCallConv(CCOld)) return false;
+ S.Context.getCanonicalCallConv(CCOld)) {
+ Attr.setInvalid();
+ return false;
+ }
if (CCOld != CC_Default) {
// Should we diagnose reapplications of the same convention?
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< FunctionType::getNameForCallConv(CC)
<< FunctionType::getNameForCallConv(CCOld);
+ Attr.setInvalid();
return false;
}
@@ -1803,6 +1862,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
if (isa<FunctionNoProtoType>(Fn)) {
S.Diag(Attr.getLoc(), diag::err_cconv_knr)
<< FunctionType::getNameForCallConv(CC);
+ Attr.setInvalid();
return false;
}
@@ -1810,6 +1870,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
if (FnP->isVariadic()) {
S.Diag(Attr.getLoc(), diag::err_cconv_varargs)
<< FunctionType::getNameForCallConv(CC);
+ Attr.setInvalid();
return false;
}
}
@@ -1829,6 +1890,7 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S
// Check the attribute arugments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
return;
}
Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
@@ -1836,12 +1898,14 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S
if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
<< "vector_size" << sizeExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
// the base type must be integer or float, and can't already be a vector.
if (CurType->isVectorType() ||
(!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
+ Attr.setInvalid();
return;
}
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
@@ -1852,11 +1916,13 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S
if (vectorSize % typeSize) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
<< sizeExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
if (vectorSize == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
<< sizeExpr->getSourceRange();
+ Attr.setInvalid();
return;
}
@@ -1873,8 +1939,12 @@ void ProcessTypeAttributeList(Sema &S, QualType &Result,
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
for (; AL; AL = AL->getNext()) {
- // If this is an attribute we can handle, do so now, otherwise, add it to
- // the LeftOverAttrs list for rechaining.
+ // Skip attributes that were marked to be invalid.
+ if (AL->isInvalid())
+ continue;
+
+ // If this is an attribute we can handle, do so now,
+ // otherwise, add it to the FnAttrs list for rechaining.
switch (AL->getKind()) {
default: break;
@@ -2029,7 +2099,10 @@ QualType Sema::BuildTypeofExprType(Expr *E) {
// function template specialization wherever deduction cannot occur.
if (FunctionDecl *Specialization
= ResolveSingleFunctionTemplateSpecialization(E)) {
- E = FixOverloadedFunctionReference(E, Specialization, Specialization);
+ // The access doesn't really matter in this case.
+ DeclAccessPair Found = DeclAccessPair::make(Specialization,
+ Specialization->getAccess());
+ E = FixOverloadedFunctionReference(E, Found, Specialization);
if (!E)
return QualType();
} else {
@@ -2049,7 +2122,10 @@ QualType Sema::BuildDecltypeType(Expr *E) {
// function template specialization wherever deduction cannot occur.
if (FunctionDecl *Specialization
= ResolveSingleFunctionTemplateSpecialization(E)) {
- E = FixOverloadedFunctionReference(E, Specialization, Specialization);
+ // The access doesn't really matter in this case.
+ DeclAccessPair Found = DeclAccessPair::make(Specialization,
+ Specialization->getAccess());
+ E = FixOverloadedFunctionReference(E, Found, Specialization);
if (!E)
return QualType();
} else {
OpenPOWER on IntegriCloud