aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2012-08-15 20:02:54 +0000
committerDimitry Andric <dim@FreeBSD.org>2012-08-15 20:02:54 +0000
commit56d91b49b13fe55c918afbda19f6165b5fbff87a (patch)
tree9abb1a658a297776086f4e0dfa6ca533de02104e /lib/Sema/SemaType.cpp
parent41e20f564abdb05101d6b2b29c59459a966c22cc (diff)
Notes
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp568
1 files changed, 351 insertions, 217 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 1400e7e5c419..20fe036348ba 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -35,19 +35,19 @@
using namespace clang;
/// isOmittedBlockReturnType - Return true if this declarator is missing a
-/// return type because this is a omitted return type on a block literal.
+/// return type because this is a omitted return type on a block literal.
static bool isOmittedBlockReturnType(const Declarator &D) {
if (D.getContext() != Declarator::BlockLiteralContext ||
D.getDeclSpec().hasTypeSpecifier())
return false;
-
+
if (D.getNumTypeObjects() == 0)
return true; // ^{ ... }
-
+
if (D.getNumTypeObjects() == 1 &&
D.getTypeObject(0).Kind == DeclaratorChunk::Function)
return true; // ^(int X, float Y) { ... }
-
+
return false;
}
@@ -59,12 +59,12 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
unsigned diagID = 0;
switch (attr.getKind()) {
- case AttributeList::AT_objc_gc:
+ case AttributeList::AT_ObjCGC:
diagID = diag::warn_pointer_attribute_wrong_type;
useExpansionLoc = true;
break;
- case AttributeList::AT_objc_ownership:
+ case AttributeList::AT_ObjCOwnership:
diagID = diag::warn_objc_object_attribute_wrong_type;
useExpansionLoc = true;
break;
@@ -93,19 +93,19 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
// objc_gc applies to Objective-C pointers or, otherwise, to the
// smallest available pointer type (i.e. 'void*' in 'void**').
#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_objc_gc: \
- case AttributeList::AT_objc_ownership
+ case AttributeList::AT_ObjCGC: \
+ case AttributeList::AT_ObjCOwnership
// Function type attributes.
#define FUNCTION_TYPE_ATTRS_CASELIST \
- case AttributeList::AT_noreturn: \
- case AttributeList::AT_cdecl: \
- case AttributeList::AT_fastcall: \
- case AttributeList::AT_stdcall: \
- case AttributeList::AT_thiscall: \
- case AttributeList::AT_pascal: \
- case AttributeList::AT_regparm: \
- case AttributeList::AT_pcs \
+ case AttributeList::AT_NoReturn: \
+ case AttributeList::AT_CDecl: \
+ case AttributeList::AT_FastCall: \
+ case AttributeList::AT_StdCall: \
+ case AttributeList::AT_ThisCall: \
+ case AttributeList::AT_Pascal: \
+ case AttributeList::AT_Regparm: \
+ case AttributeList::AT_Pcs \
namespace {
/// An object which stores processing state for the entire
@@ -284,9 +284,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
AttributeList &attr, QualType &type) {
- if (attr.getKind() == AttributeList::AT_objc_gc)
+ if (attr.getKind() == AttributeList::AT_ObjCGC)
return handleObjCGCTypeAttr(state, attr, type);
- assert(attr.getKind() == AttributeList::AT_objc_ownership);
+ assert(attr.getKind() == AttributeList::AT_ObjCOwnership);
return handleObjCOwnershipTypeAttr(state, attr, type);
}
@@ -412,7 +412,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
continue;
}
}
-
+
diagnoseBadTypeAttribute(state.getSema(), attr, type);
}
@@ -505,7 +505,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
break;
- case AttributeList::AT_ns_returns_retained:
+ case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
break;
// fallthrough
@@ -554,7 +554,8 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
// ...and *prepend* it to the declarator.
declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
/*proto*/ true,
- /*variadic*/ false, SourceLocation(),
+ /*variadic*/ false,
+ /*ambiguous*/ false, SourceLocation(),
/*args*/ 0, 0,
/*type quals*/ 0,
/*ref-qualifier*/true, SourceLocation(),
@@ -573,7 +574,8 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/// \brief Convert the specified declspec to the appropriate type
/// object.
-/// \param D the declarator containing the declaration specifier.
+/// \param state Specifies the declarator containing the declaration specifier
+/// to be converted, along with other associated processing state.
/// \returns The type described by the declaration specifiers. This function
/// never returns null.
static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
@@ -586,7 +588,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
SourceLocation DeclLoc = declarator.getIdentifierLoc();
if (DeclLoc.isInvalid())
DeclLoc = DS.getLocStart();
-
+
ASTContext &Context = S.Context;
QualType Result;
@@ -639,7 +641,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.getObjCObjectPointerType(Result);
break;
}
-
+
// If this is a missing declspec in a block literal return context, then it
// is inferred from the return statements inside the block.
// The declspec is always missing in a lambda expr context; it is either
@@ -695,7 +697,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TSW_long: Result = Context.LongTy; break;
case DeclSpec::TSW_longlong:
Result = Context.LongLongTy;
-
+
// long long is a C99 feature.
if (!S.getLangOpts().C99)
S.Diag(DS.getTypeSpecWidthLoc(),
@@ -710,7 +712,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break;
case DeclSpec::TSW_longlong:
Result = Context.UnsignedLongLongTy;
-
+
// long long is a C99 feature.
if (!S.getLangOpts().C99)
S.Diag(DS.getTypeSpecWidthLoc(),
@@ -762,10 +764,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// If the type is deprecated or unavailable, diagnose it.
S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc());
-
+
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
-
+
// TypeQuals handled by caller.
Result = Context.getTypeDeclType(D);
@@ -858,7 +860,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
- break;
+ break;
case DeclSpec::TST_auto: {
// TypeQuals handled by caller.
@@ -878,7 +880,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
- break;
+ break;
case DeclSpec::TST_error:
Result = Context.IntTy;
@@ -983,15 +985,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// C90 6.5.3 constraints: "The same type qualifier shall not appear more
// than once in the same specifier-list or qualifier-list, either directly
// or via one or more typedefs."
- if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus
+ if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus
&& TypeQuals & Result.getCVRQualifiers()) {
if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) {
- S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec)
+ S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec)
<< "const";
}
if (TypeQuals & DeclSpec::TQ_volatile && Result.isVolatileQualified()) {
- S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec)
+ S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec)
<< "volatile";
}
@@ -1036,7 +1038,7 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
ProblemTy = T->getAs<PointerType>()->getPointeeType();
- }
+ }
} else if (!Ty->isDependentType()) {
// FIXME: this deserves a proper diagnostic
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
@@ -1083,7 +1085,7 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
// If we are in an unevaluated context, like sizeof, skip adding a
// qualification.
- } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) {
+ } else if (S.isUnevaluatedContext()) {
return type;
// If that failed, give an error and recover using __strong. __strong
@@ -1157,14 +1159,14 @@ QualType Sema::BuildPointerType(QualType T,
QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
SourceLocation Loc,
DeclarationName Entity) {
- assert(Context.getCanonicalType(T) != Context.OverloadTy &&
+ assert(Context.getCanonicalType(T) != Context.OverloadTy &&
"Unresolved overloaded function type");
-
+
// C++0x [dcl.ref]p6:
- // If a typedef (7.1.3), a type template-parameter (14.3.1), or a
- // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a
- // type T, an attempt to create the type "lvalue reference to cv TR" creates
- // the type "lvalue reference to T", while an attempt to create the type
+ // If a typedef (7.1.3), a type template-parameter (14.3.1), or a
+ // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a
+ // type T, an attempt to create the type "lvalue reference to cv TR" creates
+ // the type "lvalue reference to T", while an attempt to create the type
// "rvalue reference to cv TR" creates the type TR.
bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
@@ -1205,9 +1207,20 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
// If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode
// (like gnu99, but not c99) accept any evaluatable value as an extension.
- return S.VerifyIntegerConstantExpression(
- ArraySize, &SizeVal, S.PDiag(), S.LangOpts.GNUMode,
- S.PDiag(diag::ext_vla_folded_to_constant)).isInvalid();
+ class VLADiagnoser : public Sema::VerifyICEDiagnoser {
+ public:
+ VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {}
+
+ virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
+ }
+
+ virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) {
+ S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR;
+ }
+ } Diagnoser;
+
+ return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser,
+ S.LangOpts.GNUMode).isInvalid();
}
@@ -1219,9 +1232,7 @@ static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
///
/// \param ArraySize Expression describing the size of the array.
///
-/// \param Loc The location of the entity whose type involves this
-/// array type or, if there is no such entity, the location of the
-/// type that will have array type.
+/// \param Brackets The range from the opening '[' to the closing ']'.
///
/// \param Entity The name of the entity that involves the array
/// type, if known.
@@ -1236,25 +1247,30 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (getLangOpts().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
+ // type, the (possibly cv-qualified) type void, a function type or an
// abstract class type.
//
+ // C++ [dcl.array]p3:
+ // When several "array of" specifications are adjacent, [...] only the
+ // first of the constant expressions that specify the bounds of the arrays
+ // may be omitted.
+ //
// 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()) {
+
+ if (T->isVoidType() || T->isIncompleteArrayType()) {
Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
return QualType();
}
-
- if (RequireNonAbstractType(Brackets.getBegin(), T,
+
+ 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]())
@@ -1350,7 +1366,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (ConstVal == 0) {
// GCC accepts zero sized static arrays. We allow them when
// we're not in a SFINAE context.
- Diag(ArraySize->getLocStart(),
+ Diag(ArraySize->getLocStart(),
isSFINAEContext()? diag::err_typecheck_zero_array_size
: diag::ext_typecheck_zero_array_size)
<< ArraySize->getSourceRange();
@@ -1361,9 +1377,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
<< ArraySize->getSourceRange();
ASM = ArrayType::Normal;
}
- } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
+ } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
!T->isIncompleteType()) {
- // Is the array too large?
+ // Is the array too large?
unsigned ActiveSizeBits
= ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
@@ -1371,7 +1387,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
<< ConstVal.toString(10)
<< ArraySize->getSourceRange();
}
-
+
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
@@ -1379,13 +1395,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (T->isVariableArrayType()) {
// Prohibit the use of non-POD types in VLAs.
QualType BaseT = Context.getBaseElementType(T);
- if (!T->isDependentType() &&
+ if (!T->isDependentType() &&
!BaseT.isPODType(Context) &&
!BaseT->isObjCLifetimeType()) {
Diag(Loc, diag::err_vla_non_pod)
<< BaseT;
return QualType();
- }
+ }
// Prohibit the use of VLAs during template argument deduction.
else if (isSFINAEContext()) {
Diag(Loc, diag::err_vla_in_sfinae);
@@ -1480,7 +1496,7 @@ QualType Sema::BuildFunctionType(QualType T,
SourceLocation Loc, DeclarationName Entity,
FunctionType::ExtInfo Info) {
if (T->isArrayType() || T->isFunctionType()) {
- Diag(Loc, diag::err_func_returning_array_function)
+ Diag(Loc, diag::err_func_returning_array_function)
<< T->isFunctionType() << T;
return QualType();
}
@@ -1581,18 +1597,14 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
///
/// \param T The type to which we'll be building a block pointer.
///
-/// \param CVR The cvr-qualifiers to be applied to the block pointer type.
-///
-/// \param Loc The location of the entity whose type involves this
-/// block pointer type or, if there is no such entity, the location of the
-/// type that will have block pointer type.
+/// \param Loc The source location, used for diagnostics.
///
/// \param Entity The name of the entity that involves the block pointer
/// type, if known.
///
/// \returns A suitable block pointer type, if there are no
/// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildBlockPointerType(QualType T,
+QualType Sema::BuildBlockPointerType(QualType T,
SourceLocation Loc,
DeclarationName Entity) {
if (!T->isFunctionType()) {
@@ -1688,7 +1700,7 @@ static void inferARCWriteback(TypeProcessingState &state,
// Otherwise, modify the type in-place.
Qualifiers qs;
-
+
if (declSpecType->isObjCARCImplicitlyUnretainedType())
qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone);
else
@@ -1711,7 +1723,7 @@ static void inferARCWriteback(TypeProcessingState &state,
return;
for (const AttributeList *attr = chunk.getAttrs(); attr;
attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_objc_ownership)
+ if (attr->getKind() == AttributeList::AT_ObjCOwnership)
return;
transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing,
@@ -1786,7 +1798,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
T = ConvertDeclSpecToType(state);
-
+
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
// Owned declaration is embedded in declarator.
@@ -1798,14 +1810,16 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case UnqualifiedId::IK_ConstructorTemplateId:
case UnqualifiedId::IK_DestructorName:
// Constructors and destructors don't have return types. Use
- // "void" instead.
+ // "void" instead.
T = SemaRef.Context.VoidTy;
+ if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList())
+ processTypeAttrs(state, T, true, attrs);
break;
case UnqualifiedId::IK_ConversionFunctionId:
// The result type of a conversion function is the type that it
// converts to.
- T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
+ T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
&ReturnTypeInfo);
break;
}
@@ -1890,7 +1904,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
if (DeclType.Kind == DeclaratorChunk::Function) {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- if (FTI.TrailingReturnType) {
+ if (FTI.hasTrailingReturnType()) {
Error = -1;
break;
}
@@ -2029,6 +2043,102 @@ static void checkQualifiedFunction(Sema &S, QualType T,
<< getFunctionQualifiersAsString(T->castAs<FunctionProtoType>());
}
+/// Produce an approprioate diagnostic for an ambiguity between a function
+/// declarator and a C++ direct-initializer.
+static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
+ DeclaratorChunk &DeclType, QualType RT) {
+ const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+ assert(FTI.isAmbiguous && "no direct-initializer / function ambiguity");
+
+ // If the return type is void there is no ambiguity.
+ if (RT->isVoidType())
+ return;
+
+ // An initializer for a non-class type can have at most one argument.
+ if (!RT->isRecordType() && FTI.NumArgs > 1)
+ return;
+
+ // An initializer for a reference must have exactly one argument.
+ if (RT->isReferenceType() && FTI.NumArgs != 1)
+ return;
+
+ // Only warn if this declarator is declaring a function at block scope, and
+ // doesn't have a storage class (such as 'extern') specified.
+ if (!D.isFunctionDeclarator() ||
+ D.getFunctionDefinitionKind() != FDK_Declaration ||
+ !S.CurContext->isFunctionOrMethod() ||
+ D.getDeclSpec().getStorageClassSpecAsWritten()
+ != DeclSpec::SCS_unspecified)
+ return;
+
+ // Inside a condition, a direct initializer is not permitted. We allow one to
+ // be parsed in order to give better diagnostics in condition parsing.
+ if (D.getContext() == Declarator::ConditionContext)
+ return;
+
+ SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
+
+ S.Diag(DeclType.Loc,
+ FTI.NumArgs ? diag::warn_parens_disambiguated_as_function_declaration
+ : diag::warn_empty_parens_are_function_decl)
+ << ParenRange;
+
+ // If the declaration looks like:
+ // T var1,
+ // f();
+ // and name lookup finds a function named 'f', then the ',' was
+ // probably intended to be a ';'.
+ if (!D.isFirstDeclarator() && D.getIdentifier()) {
+ FullSourceLoc Comma(D.getCommaLoc(), S.SourceMgr);
+ FullSourceLoc Name(D.getIdentifierLoc(), S.SourceMgr);
+ if (Comma.getFileID() != Name.getFileID() ||
+ Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) {
+ LookupResult Result(S, D.getIdentifier(), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ if (S.LookupName(Result, S.getCurScope()))
+ S.Diag(D.getCommaLoc(), diag::note_empty_parens_function_call)
+ << FixItHint::CreateReplacement(D.getCommaLoc(), ";")
+ << D.getIdentifier();
+ }
+ }
+
+ if (FTI.NumArgs > 0) {
+ // For a declaration with parameters, eg. "T var(T());", suggest adding parens
+ // around the first parameter to turn the declaration into a variable
+ // declaration.
+ SourceRange Range = FTI.ArgInfo[0].Param->getSourceRange();
+ SourceLocation B = Range.getBegin();
+ SourceLocation E = S.PP.getLocForEndOfToken(Range.getEnd());
+ // FIXME: Maybe we should suggest adding braces instead of parens
+ // in C++11 for classes that don't have an initializer_list constructor.
+ S.Diag(B, diag::note_additional_parens_for_variable_declaration)
+ << FixItHint::CreateInsertion(B, "(")
+ << FixItHint::CreateInsertion(E, ")");
+ } else {
+ // For a declaration without parameters, eg. "T var();", suggest replacing the
+ // parens with an initializer to turn the declaration into a variable
+ // declaration.
+ const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
+
+ // Empty parens mean value-initialization, and no parens mean
+ // default initialization. These are equivalent if the default
+ // constructor is user-provided or if zero-initialization is a
+ // no-op.
+ if (RD && RD->hasDefinition() &&
+ (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor()))
+ S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor)
+ << FixItHint::CreateRemoval(ParenRange);
+ else {
+ std::string Init = S.getFixItZeroInitializerForType(RT);
+ if (Init.empty() && S.LangOpts.CPlusPlus0x)
+ Init = "{}";
+ if (!Init.empty())
+ S.Diag(DeclType.Loc, diag::note_empty_parens_zero_initialize)
+ << FixItHint::CreateReplacement(ParenRange, Init);
+ }
+ }
+}
+
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
@@ -2165,12 +2275,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// trailing-return-type is only required if we're declaring a function,
// and not, for instance, a pointer to a function.
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
- !FTI.TrailingReturnType && chunkIndex == 0) {
+ !FTI.hasTrailingReturnType() && chunkIndex == 0) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_auto_missing_trailing_return);
T = Context.IntTy;
D.setInvalidType(true);
- } else if (FTI.TrailingReturnType) {
+ } else if (FTI.hasTrailingReturnType()) {
// T must be exactly 'auto' at this point. See CWG issue 681.
if (isa<ParenType>(T)) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
@@ -2184,10 +2294,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getDeclSpec().getSourceRange();
D.setInvalidType(true);
}
-
- T = S.GetTypeFromParser(
- ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
- &TInfo);
+ T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo);
+ if (T.isNull()) {
+ // An error occurred parsing the trailing return type.
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ }
}
}
@@ -2259,6 +2371,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< (D.getContext() == Declarator::AliasDeclContext ||
D.getContext() == Declarator::AliasTemplateContext);
+ // If we see "T var();" or "T var(T());" at block scope, it is probably
+ // an attempt to initialize a variable, not a function declaration.
+ if (FTI.isAmbiguous)
+ warnAboutAmbiguousFunction(S, D, DeclType, T);
+
if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) {
// Simple void foo(), where the incoming T is the result type.
T = Context.getFunctionNoProtoType(T);
@@ -2270,7 +2387,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
bool Overloadable = false;
for (const AttributeList *Attrs = D.getAttributes();
Attrs; Attrs = Attrs->getNext()) {
- if (Attrs->getKind() == AttributeList::AT_overloadable) {
+ if (Attrs->getKind() == AttributeList::AT_Overloadable) {
Overloadable = true;
break;
}
@@ -2290,12 +2407,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = FTI.isVariadic;
- EPI.HasTrailingReturn = FTI.TrailingReturnType;
+ EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
EPI.TypeQuals = FTI.TypeQuals;
EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
: FTI.RefQualifierIsLValueRef? RQ_LValue
: RQ_RValue;
-
+
// Otherwise, we have a function with an argument list that is
// potentially variadic.
SmallVector<QualType, 16> ArgTys;
@@ -2311,7 +2428,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
assert(!ArgTy.isNull() && "Couldn't parse type?");
// Adjust the parameter type.
- assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&
+ assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&
"Unadjusted type?");
// Look for 'void'. void is allowed only as a single argument to a
@@ -2374,7 +2491,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
SmallVector<ParsedType, 2> DynamicExceptions;
SmallVector<SourceRange, 2> DynamicExceptionRanges;
Expr *NoexceptExpr = 0;
-
+
if (FTI.getExceptionSpecType() == EST_Dynamic) {
// FIXME: It's rather inefficient to have to split into two vectors
// here.
@@ -2388,14 +2505,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
} else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
NoexceptExpr = FTI.NoexceptExpr;
}
-
+
S.checkExceptionSpecification(FTI.getExceptionSpecType(),
DynamicExceptions,
DynamicExceptionRanges,
NoexceptExpr,
Exceptions,
EPI);
-
+
if (FTI.getExceptionSpecType() == EST_None &&
ImplicitlyNoexcept && chunkIndex == 0) {
// Only the outermost chunk is marked noexcept, of course.
@@ -2475,7 +2592,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
- // C++ 8.3.5p4:
+ // C++ 8.3.5p4:
// A cv-qualifier-seq shall only be part of the function type
// for a nonstatic member function, the function type to which a pointer
// to member refers, or the top-level function type of a function typedef
@@ -2503,7 +2620,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Rebuild function type adding a 'const' qualifier.
FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
EPI.TypeQuals |= DeclSpec::TQ_const;
- T = Context.getFunctionType(FnTy->getResultType(),
+ T = Context.getFunctionType(FnTy->getResultType(),
FnTy->arg_type_begin(),
FnTy->getNumArgs(), EPI);
}
@@ -2540,7 +2657,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// RemovalLocs.push_back(Chunk.Fun.getRestrictQualifierLoc());
if (!RemovalLocs.empty()) {
std::sort(RemovalLocs.begin(), RemovalLocs.end(),
- SourceManager::LocBeforeThanCompare(S.getSourceManager()));
+ BeforeThanCompare<SourceLocation>(S.getSourceManager()));
RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
Loc = RemovalLocs.front();
}
@@ -2556,7 +2673,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
- T = Context.getFunctionType(FnTy->getResultType(),
+ T = Context.getFunctionType(FnTy->getResultType(),
FnTy->arg_type_begin(),
FnTy->getNumArgs(), EPI);
}
@@ -2572,31 +2689,31 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// C++0x [dcl.constexpr]p9:
// A constexpr specifier used in an object declaration declares the object
- // as const.
+ // as const.
if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) {
T.addConst();
}
- // If there was an ellipsis in the declarator, the declaration declares a
+ // If there was an ellipsis in the declarator, the declaration declares a
// parameter pack whose type may be a pack expansion type.
if (D.hasEllipsis() && !T.isNull()) {
// C++0x [dcl.fct]p13:
- // A declarator-id or abstract-declarator containing an ellipsis shall
+ // A declarator-id or abstract-declarator containing an ellipsis shall
// only be used in a parameter-declaration. Such a parameter-declaration
// is a parameter pack (14.5.3). [...]
switch (D.getContext()) {
case Declarator::PrototypeContext:
// C++0x [dcl.fct]p13:
- // [...] When it is part of a parameter-declaration-clause, the
- // parameter pack is a function parameter pack (14.5.3). The type T
+ // [...] When it is part of a parameter-declaration-clause, the
+ // parameter pack is a function parameter pack (14.5.3). The type T
// of the declarator-id of the function parameter pack shall contain
- // a template parameter pack; each template parameter pack in T is
+ // a template parameter pack; each template parameter pack in T is
// expanded by the function parameter pack.
//
// We represent function parameter packs as function parameters whose
// type is a pack expansion.
if (!T->containsUnexpandedParameterPack()) {
- S.Diag(D.getEllipsisLoc(),
+ S.Diag(D.getEllipsisLoc(),
diag::err_function_parameter_pack_without_parameter_packs)
<< T << D.getSourceRange();
D.setEllipsisLoc(SourceLocation());
@@ -2604,10 +2721,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
}
break;
-
+
case Declarator::TemplateParamContext:
// C++0x [temp.param]p15:
- // If a template-parameter is a [...] is a parameter-declaration that
+ // If a template-parameter is a [...] is a parameter-declaration that
// declares a parameter pack (8.3.5), then the template-parameter is a
// template parameter pack (14.5.3).
//
@@ -2622,7 +2739,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
break;
-
+
case Declarator::FileContext:
case Declarator::KNRTypeListContext:
case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
@@ -2675,7 +2792,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount)
inferARCWriteback(state, T);
-
+
return GetFullTypeForDeclarator(state, T, ReturnTypeInfo);
}
@@ -2700,7 +2817,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
for (const AttributeList *attr = chunk.getAttrs(); attr;
attr = attr->getNext())
- if (attr->getKind() == AttributeList::AT_objc_ownership)
+ if (attr->getKind() == AttributeList::AT_ObjCOwnership)
return;
const char *attrStr = 0;
@@ -2718,14 +2835,13 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
.create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
/*scope*/ 0, SourceLocation(),
&S.Context.Idents.get(attrStr), SourceLocation(),
- /*args*/ 0, 0,
- /*declspec*/ false, /*C++0x*/ false);
+ /*args*/ 0, 0, AttributeList::AS_GNU);
spliceAttrIntoList(*attr, chunk.getAttrListRef());
// TODO: mark whether we did this inference?
}
-/// \brief Used for transfering ownership in casts resulting in l-values.
+/// \brief Used for transferring ownership in casts resulting in l-values.
static void transferARCOwnership(TypeProcessingState &state,
QualType &declSpecTy,
Qualifiers::ObjCLifetime ownership) {
@@ -2763,7 +2879,7 @@ static void transferARCOwnership(TypeProcessingState &state,
if (inner == -1)
return;
- DeclaratorChunk &chunk = D.getTypeObject(inner);
+ DeclaratorChunk &chunk = D.getTypeObject(inner);
if (chunk.Kind == DeclaratorChunk::Pointer) {
if (declSpecTy->isObjCRetainableType())
return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
@@ -2797,33 +2913,33 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
switch (kind) {
case AttributedType::attr_address_space:
- return AttributeList::AT_address_space;
+ return AttributeList::AT_AddressSpace;
case AttributedType::attr_regparm:
- return AttributeList::AT_regparm;
+ return AttributeList::AT_Regparm;
case AttributedType::attr_vector_size:
- return AttributeList::AT_vector_size;
+ return AttributeList::AT_VectorSize;
case AttributedType::attr_neon_vector_type:
- return AttributeList::AT_neon_vector_type;
+ return AttributeList::AT_NeonVectorType;
case AttributedType::attr_neon_polyvector_type:
- return AttributeList::AT_neon_polyvector_type;
+ return AttributeList::AT_NeonPolyVectorType;
case AttributedType::attr_objc_gc:
- return AttributeList::AT_objc_gc;
+ return AttributeList::AT_ObjCGC;
case AttributedType::attr_objc_ownership:
- return AttributeList::AT_objc_ownership;
+ return AttributeList::AT_ObjCOwnership;
case AttributedType::attr_noreturn:
- return AttributeList::AT_noreturn;
+ return AttributeList::AT_NoReturn;
case AttributedType::attr_cdecl:
- return AttributeList::AT_cdecl;
+ return AttributeList::AT_CDecl;
case AttributedType::attr_fastcall:
- return AttributeList::AT_fastcall;
+ return AttributeList::AT_FastCall;
case AttributedType::attr_stdcall:
- return AttributeList::AT_stdcall;
+ return AttributeList::AT_StdCall;
case AttributedType::attr_thiscall:
- return AttributeList::AT_thiscall;
+ return AttributeList::AT_ThisCall;
case AttributedType::attr_pascal:
- return AttributeList::AT_pascal;
+ return AttributeList::AT_Pascal;
case AttributedType::attr_pcs:
- return AttributeList::AT_pcs;
+ return AttributeList::AT_Pcs;
}
llvm_unreachable("unexpected attribute kind!");
}
@@ -2856,7 +2972,7 @@ namespace {
const DeclSpec &DS;
public:
- TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
+ TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
: Context(Context), DS(DS) {}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
@@ -2871,6 +2987,10 @@ namespace {
}
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ // FIXME. We should have DS.getTypeSpecTypeEndLoc(). But, it requires
+ // addition field. What we have is good enough for dispay of location
+ // of 'fixit' on interface name.
+ TL.setNameEndLoc(DS.getLocEnd());
}
void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
// Handle the base type, which might not have been written explicitly.
@@ -3000,7 +3120,7 @@ namespace {
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
-
+
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
@@ -3104,7 +3224,7 @@ namespace {
assert(Chunk.Kind == DeclaratorChunk::Function);
TL.setLocalRangeBegin(Chunk.Loc);
TL.setLocalRangeEnd(Chunk.EndLoc);
- TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType);
+ TL.setTrailingReturn(Chunk.Fun.hasTrailingReturnType());
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
@@ -3142,9 +3262,9 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
// Handle parameter packs whose type is a pack expansion.
if (isa<PackExpansionType>(T)) {
cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc());
- CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
+ CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
-
+
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
while (isa<AttributedTypeLoc>(CurrTL)) {
AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL);
@@ -3155,7 +3275,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
-
+
// If we have different source information for the return type, use
// that. This really only applies to C++ conversion functions.
if (ReturnTypeInfo) {
@@ -3165,7 +3285,7 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
} else {
TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
}
-
+
return TInfo;
}
@@ -3174,7 +3294,7 @@ ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
// FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
// and Sema during declaration parsing. Try deallocating/caching them when
// it's appropriate, instead of allocating them and keeping them around.
- LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType),
+ LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType),
TypeAlignment);
new (LocT) LocInfoType(T, TInfo);
assert(LocT->getTypeClass() != T->getTypeClass() &&
@@ -3304,13 +3424,13 @@ static bool hasDirectOwnershipQualifier(QualType type) {
// X *__strong (...)
} else if (const ParenType *paren = dyn_cast<ParenType>(type)) {
type = paren->getInnerType();
-
+
// That's it for things we want to complain about. In particular,
// we do not want to look through typedefs, typeof(expr),
// typeof(type), or any other way that the type is somehow
// abstracted.
} else {
-
+
return false;
}
}
@@ -3439,8 +3559,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
attr.setInvalid();
return true;
}
-
- // Forbid __weak for class objects marked as
+
+ // Forbid __weak for class objects marked as
// objc_arc_weak_reference_unavailable
if (lifetime == Qualifiers::OCL_Weak) {
QualType T = type;
@@ -3450,12 +3570,12 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
if (Class->isArcWeakrefUnavailable()) {
S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
- S.Diag(ObjT->getInterfaceDecl()->getLocation(),
+ S.Diag(ObjT->getInterfaceDecl()->getLocation(),
diag::note_class_declared);
}
}
}
-
+
return true;
}
@@ -3654,7 +3774,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
FunctionTypeUnwrapper unwrapped(S, type);
- if (attr.getKind() == AttributeList::AT_noreturn) {
+ if (attr.getKind() == AttributeList::AT_NoReturn) {
if (S.CheckNoReturnAttr(attr))
return true;
@@ -3670,7 +3790,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
// ns_returns_retained is not always a type attribute, but if we got
// here, we're treating it as one right now.
- if (attr.getKind() == AttributeList::AT_ns_returns_retained) {
+ if (attr.getKind() == AttributeList::AT_NSReturnsRetained) {
assert(S.getLangOpts().ObjCAutoRefCount &&
"ns_returns_retained treated as type attribute in non-ARC");
if (attr.getNumArgs()) return true;
@@ -3685,7 +3805,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
- if (attr.getKind() == AttributeList::AT_regparm) {
+ if (attr.getKind() == AttributeList::AT_Regparm) {
unsigned value;
if (S.CheckRegparmAttr(attr, value))
return true;
@@ -3705,7 +3825,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
- FunctionType::ExtInfo EI =
+ FunctionType::ExtInfo EI =
unwrapped.get()->getExtInfo().withRegParm(value);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
@@ -3860,11 +3980,11 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
/// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
/// a type.
-static void HandleExtVectorTypeAttr(QualType &CurType,
- const AttributeList &Attr,
+static void HandleExtVectorTypeAttr(QualType &CurType,
+ const AttributeList &Attr,
Sema &S) {
Expr *sizeExpr;
-
+
// Special case where the argument is a template id.
if (Attr.getParameterName()) {
CXXScopeSpec SS;
@@ -3876,7 +3996,7 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
id, false, false);
if (Size.isInvalid())
return;
-
+
sizeExpr = Size.get();
} else {
// check the attribute arguments.
@@ -3886,7 +4006,7 @@ static void HandleExtVectorTypeAttr(QualType &CurType,
}
sizeExpr = Attr.getArg(0);
}
-
+
// Create the vector type.
QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
if (!T.isNull())
@@ -3973,12 +4093,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
switch (attr.getKind()) {
default: break;
- case AttributeList::AT_may_alias:
+ case AttributeList::AT_MayAlias:
// FIXME: This attribute needs to actually be handled, but if we ignore
// it it breaks large amounts of Linux software.
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_address_space:
+ case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
@@ -3987,35 +4107,42 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
distributeObjCPointerTypeAttr(state, attr, type);
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_vector_size:
+ case AttributeList::AT_VectorSize:
HandleVectorSizeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_ext_vector_type:
+ case AttributeList::AT_ExtVectorType:
if (state.getDeclarator().getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_typedef)
HandleExtVectorTypeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_neon_vector_type:
+ case AttributeList::AT_NeonVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonVector, "neon_vector_type");
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_neon_polyvector_type:
+ case AttributeList::AT_NeonPolyVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonPolyVector,
"neon_polyvector_type");
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_opencl_image_access:
+ case AttributeList::AT_OpenCLImageAccess:
HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
- case AttributeList::AT_ns_returns_retained:
+ case AttributeList::AT_Win64:
+ case AttributeList::AT_Ptr32:
+ case AttributeList::AT_Ptr64:
+ // FIXME: don't ignore these
+ attr.setUsedAsTypeAttr();
+ break;
+
+ case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
- break;
+ break;
// fallthrough into the function attrs
FUNCTION_TYPE_ATTRS_CASELIST:
@@ -4043,14 +4170,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
/// case of a reference type, the referred-to type).
///
/// \param E The expression whose type is required to be complete.
-/// \param PD The partial diagnostic that will be printed out if the type cannot
-/// be completed.
+/// \param Diagnoser The object that will emit a diagnostic if the type is
+/// incomplete.
///
/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
/// otherwise.
-bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
- std::pair<SourceLocation,
- PartialDiagnostic> Note) {
+bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){
QualType T = E->getType();
// Fast path the case where the type is already complete.
@@ -4065,7 +4190,7 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
if (Var->isStaticDataMember() &&
Var->getInstantiatedFromStaticDataMember()) {
-
+
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
assert(MSInfo && "Missing member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
@@ -4073,15 +4198,15 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
// If we don't already have a point of instantiation, this is it.
if (MSInfo->getPointOfInstantiation().isInvalid()) {
MSInfo->setPointOfInstantiation(E->getLocStart());
-
- // This is a modification of an existing AST node. Notify
+
+ // This is a modification of an existing AST node. Notify
// listeners.
if (ASTMutationListener *L = getASTMutationListener())
L->StaticDataMemberInstantiated(Var);
}
-
+
InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var);
-
+
// Update the type to the newly instantiated definition's type both
// here and within the expression.
if (VarDecl *Def = Var->getDefinition()) {
@@ -4091,7 +4216,7 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
E->setType(T);
}
}
-
+
// We still go on to try to complete the type independently, as it
// may also require instantiations or diagnostics if it remains
// incomplete.
@@ -4107,7 +4232,26 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
if (const ReferenceType *Ref = T->getAs<ReferenceType>())
T = Ref->getPointeeType();
- return RequireCompleteType(E->getExprLoc(), T, PD, Note);
+ return RequireCompleteType(E->getExprLoc(), T, Diagnoser);
+}
+
+namespace {
+ struct TypeDiagnoserDiag : Sema::TypeDiagnoser {
+ unsigned DiagID;
+
+ TypeDiagnoserDiag(unsigned DiagID)
+ : Sema::TypeDiagnoser(DiagID == 0), DiagID(DiagID) {}
+
+ virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ if (Suppressed) return;
+ S.Diag(Loc, DiagID) << T;
+ }
+ };
+}
+
+bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
+ TypeDiagnoserDiag Diagnoser(DiagID);
+ return RequireCompleteExprType(E, Diagnoser);
}
/// @brief Ensure that the type T is a complete type.
@@ -4125,17 +4269,10 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
///
/// @param T The type that this routine is examining for completeness.
///
-/// @param PD The partial diagnostic that will be printed out if T is not a
-/// complete type.
-///
/// @returns @c true if @p T is incomplete and a diagnostic was emitted,
/// @c false otherwise.
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD,
- std::pair<SourceLocation,
- PartialDiagnostic> Note) {
- unsigned diag = PD.getDiagID();
-
+ TypeDiagnoser &Diagnoser) {
// FIXME: Add this assertion to make sure we always get instantiation points.
// assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
// FIXME: Add this assertion to help us flush out problems with
@@ -4148,9 +4285,9 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
NamedDecl *Def = 0;
if (!T->isIncompleteType(&Def)) {
// If we know about the definition but it is not visible, complain.
- if (diag != 0 && Def && !LookupResult::isVisible(Def)) {
+ if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(Def)) {
// Suppress this error outside of a SFINAE context if we've already
- // emitted the error once for this type. There's no usefulness in
+ // emitted the error once for this type. There's no usefulness in
// repeating the diagnostic.
// FIXME: Add a Fix-It that imports the corresponding module or includes
// the header.
@@ -4159,13 +4296,13 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
Diag(Def->getLocation(), diag::note_previous_definition);
}
}
-
+
return false;
}
const TagType *Tag = T->getAs<TagType>();
const ObjCInterfaceType *IFace = 0;
-
+
if (Tag) {
// Avoid diagnosing invalid decls as incomplete.
if (Tag->getDecl()->isInvalidDecl())
@@ -4182,7 +4319,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
// Avoid diagnosing invalid decls as incomplete.
if (IFace->getDecl()->isInvalidDecl())
return true;
-
+
// Give the external AST source a chance to complete the type.
if (IFace->getDecl()->hasExternalLexicalStorage()) {
Context.getExternalSource()->CompleteType(IFace->getDecl());
@@ -4190,7 +4327,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return false;
}
}
-
+
// If we have a class template specialization or a class member of a
// class template specialization, or an array with known size of such,
// try to instantiate it.
@@ -4204,7 +4341,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
TSK_ImplicitInstantiation,
- /*Complain=*/diag != 0);
+ /*Complain=*/!Diagnoser.Suppressed);
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
@@ -4216,21 +4353,17 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return InstantiateClass(Loc, Rec, Pattern,
getTemplateInstantiationArgs(Rec),
TSK_ImplicitInstantiation,
- /*Complain=*/diag != 0);
+ /*Complain=*/!Diagnoser.Suppressed);
}
}
}
- if (diag == 0)
+ if (Diagnoser.Suppressed)
return true;
-
+
// We have an incomplete type. Produce a diagnostic.
- Diag(Loc, PD) << T;
-
- // If we have a note, produce it.
- if (!Note.first.isInvalid())
- Diag(Note.first, Note.second);
-
+ Diagnoser.diagnose(*this, Loc, T);
+
// If the type was a forward declaration of a class/struct/union
// type, produce a note.
if (Tag && !Tag->getDecl()->isInvalidDecl())
@@ -4238,7 +4371,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
Tag->isBeingDefined() ? diag::note_type_being_defined
: diag::note_forward_declaration)
<< QualType(Tag, 0);
-
+
// If the Objective-C class was a forward declaration, produce a note.
if (IFace && !IFace->getDecl()->isInvalidDecl())
Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
@@ -4247,15 +4380,9 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
}
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD) {
- return RequireCompleteType(Loc, T, PD,
- std::make_pair(SourceLocation(), PDiag(0)));
-}
-
-bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID) {
- return RequireCompleteType(Loc, T, PDiag(DiagID),
- std::make_pair(SourceLocation(), PDiag(0)));
+ TypeDiagnoserDiag Diagnoser(DiagID);
+ return RequireCompleteType(Loc, T, Diagnoser);
}
/// @brief Ensure that the type T is a literal type.
@@ -4272,13 +4399,12 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
///
/// @param T The type that this routine is examining for literalness.
///
-/// @param PD The partial diagnostic that will be printed out if T is not a
-/// literal type.
+/// @param Diagnoser Emits a diagnostic if T is not a literal type.
///
/// @returns @c true if @p T is not a literal type and a diagnostic was emitted,
/// @c false otherwise.
bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD) {
+ TypeDiagnoser &Diagnoser) {
assert(!T->isDependentType() && "type should not be dependent");
QualType ElemType = Context.getBaseElementType(T);
@@ -4287,10 +4413,10 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
if (T->isLiteralType())
return false;
- if (PD.getDiagID() == 0)
+ if (Diagnoser.Suppressed)
return true;
- Diag(Loc, PD) << T;
+ Diagnoser.diagnose(*this, Loc, T);
if (T->isVariableArrayType())
return true;
@@ -4301,9 +4427,13 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- // FIXME: Better diagnostic for incomplete class?
- if (!RD->isCompleteDefinition())
+ // A partially-defined class type can't be a literal type, because a literal
+ // class type must have a trivial destructor (which can't be checked until
+ // the class definition is complete).
+ if (!RD->isCompleteDefinition()) {
+ RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T);
return true;
+ }
// If the class has virtual base classes, then it's not an aggregate, and
// cannot have any constexpr constructors or a trivial default constructor,
@@ -4331,11 +4461,11 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
}
for (CXXRecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I != E; ++I) {
- if (!(*I)->getType()->isLiteralType() ||
- (*I)->getType().isVolatileQualified()) {
- Diag((*I)->getLocation(), diag::note_non_literal_field)
- << RD << (*I) << (*I)->getType()
- << (*I)->getType().isVolatileQualified();
+ if (!I->getType()->isLiteralType() ||
+ I->getType().isVolatileQualified()) {
+ Diag(I->getLocation(), diag::note_non_literal_field)
+ << RD << *I << I->getType()
+ << I->getType().isVolatileQualified();
return true;
}
}
@@ -4355,6 +4485,11 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
return true;
}
+bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
+ TypeDiagnoserDiag Diagnoser(DiagID);
+ return RequireLiteralType(Loc, T, Diagnoser);
+}
+
/// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
/// and qualified by the nested-name-specifier contained in SS.
QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
@@ -4396,8 +4531,8 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
// The type denoted by decltype(e) is defined as follows:
//
// - if e is an unparenthesized id-expression or an unparenthesized class
- // member access (5.2.5), decltype(e) is the type of the entity named
- // by e. If there is no such entity, or if e names a set of overloaded
+ // member access (5.2.5), decltype(e) is the type of the entity named
+ // by e. If there is no such entity, or if e names a set of overloaded
// functions, the program is ill-formed;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
@@ -4407,7 +4542,7 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
return FD->getType();
}
-
+
// C++11 [expr.lambda.prim]p18:
// Every occurrence of decltype((x)) where x is a possibly
// parenthesized id-expression that names an entity of automatic
@@ -4433,16 +4568,16 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) {
// [...]
QualType T = E->getType();
switch (E->getValueKind()) {
- // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the
+ // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the
// type of e;
case VK_XValue: T = S.Context.getRValueReferenceType(T); break;
- // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the
+ // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the
// type of e;
case VK_LValue: T = S.Context.getLValueReferenceType(T); break;
// - otherwise, decltype(e) is the type of e.
case VK_RValue: break;
}
-
+
return T;
}
@@ -4450,7 +4585,7 @@ QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
ExprResult ER = CheckPlaceholderExpr(E);
if (ER.isInvalid()) return QualType();
E = ER.take();
-
+
return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
}
@@ -4482,8 +4617,7 @@ QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
if (!T->isDependentType()) {
// FIXME: It isn't entirely clear whether incomplete atomic types
// are allowed or not; for simplicity, ban them for the moment.
- if (RequireCompleteType(Loc, T,
- PDiag(diag::err_atomic_specifier_bad_type) << 0))
+ if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0))
return QualType();
int DisallowedKind = -1;