Give InitListChecker a verification-only mode, where it neither emits diagnostics nor

builds a semantic (structured) initializer list, just reports on whether it can match
the given list to the target type.
Use this mode for doing init list checking in the initial step of initialization, which
will eventually allow us to do overload resolution based on the outcome.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140457 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sebastian Redl 2011-09-24 17:48:00 +00:00
Родитель 8713d4e874
Коммит 14b0c194b3
6 изменённых файлов: 366 добавлений и 242 удалений

Просмотреть файл

@ -810,7 +810,7 @@ public:
void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
QualType T);
/// \brief Add a list-initialiation step
/// \brief Add a list-initialiation step.
void AddListInitializationStep(QualType T);
/// \brief Add a constructor-initialization step.

Просмотреть файл

@ -464,6 +464,7 @@ namespace clang {
bool isEllipsis() const { return getKind() == EllipsisConversion; }
bool isAmbiguous() const { return getKind() == AmbiguousConversion; }
bool isUserDefined() const { return getKind() == UserDefinedConversion; }
bool isFailure() const { return isBad() || isAmbiguous(); }
/// Determines whether this conversion sequence has been
/// initialized. Most operations should never need to query

Просмотреть файл

@ -2217,8 +2217,9 @@ public:
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
bool CanUseDecl(NamedDecl *D);
bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
const ObjCInterfaceDecl *UnknownObjCClass=0);
const ObjCInterfaceDecl *UnknownObjCClass = 0);
std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD);
bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
ObjCMethodDecl *Getter,
@ -5580,7 +5581,8 @@ public:
// CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
// this routine performs the default function/array converions.
AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType,
ExprResult &RHS);
ExprResult &RHS,
bool Diagnose = true);
// \brief If the lhs type is a transparent union, check whether we
// can initialize the transparent union with the given expression.
@ -5593,11 +5595,13 @@ public:
ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action,
bool AllowExplicit = false);
bool AllowExplicit = false,
bool Diagnose = true);
ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action,
bool AllowExplicit,
ImplicitConversionSequence& ICS);
ImplicitConversionSequence& ICS,
bool Diagnose = true);
ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
const ImplicitConversionSequence& ICS,
AssignmentAction Action,

Просмотреть файл

@ -41,6 +41,20 @@
using namespace clang;
using namespace sema;
/// \brief Determine whether the use of this declaration is valid, without
/// emitting diagnostics.
bool Sema::CanUseDecl(NamedDecl *D) {
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D))
return false;
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted())
return false;
}
return true;
}
/// \brief Determine whether the use of this declaration is valid, and
/// emit any corresponding diagnostics.
@ -51,9 +65,6 @@ using namespace sema;
/// used, or produce an error (and return true) if a C++0x deleted
/// function is being used.
///
/// If IgnoreDeprecated is set to true, this should not warn about deprecated
/// decls.
///
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
///
@ -5659,7 +5670,8 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
}
Sema::AssignConvertType
Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS) {
Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
bool Diagnose) {
if (getLangOptions().CPlusPlus) {
if (!LHSType->isRecordType()) {
// C++ 5.17p3: If the left operand is not of class type, the
@ -5667,7 +5679,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS) {
// cv-unqualified type of the left operand.
ExprResult Res = PerformImplicitConversion(RHS.get(),
LHSType.getUnqualifiedType(),
AA_Assigning);
AA_Assigning, Diagnose);
if (Res.isInvalid())
return Incompatible;
Sema::AssignConvertType result = Compatible;

Просмотреть файл

@ -169,6 +169,7 @@ namespace {
class InitListChecker {
Sema &SemaRef;
bool hadError;
bool VerifyOnly; // no diagnostics, no structure building
std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
InitListExpr *FullyStructuredList;
@ -257,7 +258,7 @@ class InitListChecker {
bool TopLevelObject);
public:
InitListChecker(Sema &S, const InitializedEntity &Entity,
InitListExpr *IL, QualType &T);
InitListExpr *IL, QualType &T, bool VerifyOnly);
bool HadError() { return hadError; }
// @brief Retrieves the fully-structured initializer list used for
@ -450,8 +451,9 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
InitListExpr *IL, QualType &T)
: SemaRef(S) {
InitListExpr *IL, QualType &T,
bool VerifyOnly)
: SemaRef(S), VerifyOnly(VerifyOnly) {
hadError = false;
unsigned newIndex = 0;
@ -462,7 +464,7 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
FullyStructuredList, newStructuredIndex,
/*TopLevelObject=*/true);
if (!hadError) {
if (!hadError && !VerifyOnly) {
bool RequiresSecondPass = false;
FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
if (RequiresSecondPass && !hadError)
@ -513,6 +515,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
llvm_unreachable("CheckImplicitInitList(): Illegal type");
if (maxElements == 0) {
if (!VerifyOnly)
SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
diag::err_implicit_empty_initializer);
++Index;
@ -535,6 +538,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
StructuredSubobjectInitList,
StructuredSubobjectInitIndex);
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
if (!VerifyOnly) {
StructuredSubobjectInitList->setType(T);
// Update the structured sub-object initializer so that it's ending
@ -550,12 +554,14 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
diag::warn_missing_braces)
<< StructuredSubobjectInitList->getSourceRange()
<< FixItHint::CreateInsertion(StructuredSubobjectInitList->getLocStart(),
"{")
<< FixItHint::CreateInsertion(SemaRef.PP.getLocForEndOfToken(
<< FixItHint::CreateInsertion(
StructuredSubobjectInitList->getLocStart(), "{")
<< FixItHint::CreateInsertion(
SemaRef.PP.getLocForEndOfToken(
StructuredSubobjectInitList->getLocEnd()),
"}");
}
}
}
void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
@ -565,18 +571,31 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
unsigned &StructuredIndex,
bool TopLevelObject) {
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
if (!VerifyOnly) {
SyntacticToSemantic[IList] = StructuredList;
StructuredList->setSyntacticForm(IList);
}
CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
Index, StructuredList, StructuredIndex, TopLevelObject);
if (!VerifyOnly) {
QualType ExprTy = T.getNonLValueExprType(SemaRef.Context);
IList->setType(ExprTy);
StructuredList->setType(ExprTy);
}
if (hadError)
return;
if (Index < IList->getNumInits()) {
// We have leftover initializers
if (VerifyOnly) {
if (SemaRef.getLangOptions().CPlusPlus ||
(SemaRef.getLangOptions().OpenCL &&
IList->getType()->isVectorType())) {
hadError = true;
}
return;
}
if (StructuredIndex == 1 &&
IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) {
unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
@ -613,7 +632,8 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
}
}
if (T->isScalarType() && IList->getNumInits() == 1 && !TopLevelObject)
if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 &&
!TopLevelObject)
SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
<< IList->getSourceRange()
<< FixItHint::CreateRemoval(IList->getLocStart())
@ -658,6 +678,7 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
} else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
// This type is invalid, issue a diagnostic.
++Index;
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
<< DeclType;
hadError = true;
@ -670,6 +691,7 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
// we have an initializer list and a destination type that is not
// an aggregate.
// FIXME: In C++0x, this is yet another form of initialization.
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
<< DeclType << IList->getSourceRange();
hadError = true;
@ -677,10 +699,12 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
CheckReferenceType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
} else if (DeclType->isObjCObjectType()) {
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class)
<< DeclType;
hadError = true;
} else {
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
<< DeclType;
hadError = true;
@ -741,6 +765,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
if (Seq) {
if (!VerifyOnly) {
ExprResult Result =
Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
if (Result.isInvalid())
@ -748,6 +773,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
UpdateStructuredListElement(StructuredList, StructuredIndex,
Result.takeAs<Expr>());
}
++Index;
return;
}
@ -764,7 +790,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// that of the expression.
ExprResult ExprRes = SemaRef.Owned(expr);
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes)
SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
!VerifyOnly)
== Sema::Compatible) {
if (ExprRes.isInvalid())
hadError = true;
@ -794,11 +821,13 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
StructuredIndex);
++StructuredIndex;
} else {
if (!VerifyOnly) {
// We cannot initialize this element, so let
// PerformCopyInitialization produce the appropriate diagnostic.
SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
SemaRef.Owned(expr),
/*TopLevelOfInitList=*/true);
}
hadError = true;
++Index;
++StructuredIndex;
@ -825,7 +854,7 @@ void InitListChecker::CheckComplexType(const InitializedEntity &Entity,
// This is an extension in C. (The builtin _Complex type does not exist
// in the C++ standard.)
if (!SemaRef.getLangOptions().CPlusPlus)
if (!SemaRef.getLangOptions().CPlusPlus && !VerifyOnly)
SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init)
<< IList->getSourceRange();
@ -848,6 +877,8 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
if (Index >= IList->getNumInits()) {
// FIXME: Allowed in C++11.
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
<< IList->getSourceRange();
hadError = true;
@ -858,6 +889,7 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
Expr *expr = IList->getInit(Index);
if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
if (!VerifyOnly)
SemaRef.Diag(SubIList->getLocStart(),
diag::warn_many_braces_around_scalar_init)
<< SubIList->getSourceRange();
@ -866,6 +898,7 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
StructuredIndex);
return;
} else if (isa<DesignatedInitExpr>(expr)) {
if (!VerifyOnly)
SemaRef.Diag(expr->getSourceRange().getBegin(),
diag::err_designator_for_scalar_init)
<< DeclType << expr->getSourceRange();
@ -875,6 +908,13 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
return;
}
if (VerifyOnly) {
if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
hadError = true;
++Index;
return;
}
ExprResult Result =
SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
SemaRef.Owned(expr),
@ -904,9 +944,26 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
if (Index < IList->getNumInits()) {
if (Index >= IList->getNumInits()) {
// FIXME: It would be wonderful if we could point at the actual member. In
// general, it would be useful to pass location information down the stack,
// so that we know the location (or decl) of the "current object" being
// initialized.
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(),
diag::err_init_reference_member_uninitialized)
<< DeclType
<< IList->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
return;
}
Expr *expr = IList->getInit(Index);
if (isa<InitListExpr>(expr)) {
// FIXME: Allowed in C++11.
if (!VerifyOnly)
SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
<< DeclType << IList->getSourceRange();
hadError = true;
@ -915,6 +972,13 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
return;
}
if (VerifyOnly) {
if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
hadError = true;
++Index;
return;
}
ExprResult Result =
SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
SemaRef.Owned(expr),
@ -931,20 +995,6 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
else
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
} else {
// FIXME: It would be wonderful if we could point at the actual member. In
// general, it would be useful to pass location information down the stack,
// so that we know the location (or decl) of the "current object" being
// initialized.
SemaRef.Diag(IList->getLocStart(),
diag::err_init_reference_member_uninitialized)
<< DeclType
<< IList->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
return;
}
}
void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
@ -965,6 +1015,13 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
// instead of breaking it apart (which is doomed to failure anyway).
Expr *Init = IList->getInit(Index);
if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) {
if (VerifyOnly) {
if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(Init)))
hadError = true;
++Index;
return;
}
ExprResult Result =
SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(),
SemaRef.Owned(Init),
@ -984,7 +1041,8 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
if (hadError)
++StructuredIndex;
else
UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
UpdateStructuredListElement(StructuredList, StructuredIndex,
ResultExpr);
++Index;
return;
}
@ -1037,8 +1095,8 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
}
// OpenCL requires all elements to be initialized.
if (numEltsInit != maxElements)
if (SemaRef.getLangOptions().OpenCL)
// FIXME: Shouldn't this set hadError to true then?
if (numEltsInit != maxElements && !VerifyOnly)
SemaRef.Diag(IList->getSourceRange().getBegin(),
diag::err_vector_incorrect_num_initializers)
<< (numEltsInit < maxElements) << maxElements << numEltsInit;
@ -1063,8 +1121,10 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// of the structured initializer list doesn't match exactly,
// because doing so would involve allocating one character
// constant for each string.
if (!VerifyOnly) {
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
}
++Index;
return;
}
@ -1073,6 +1133,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// Check for VLAs; in standard C it would be possible to check this
// earlier, but I don't know where clang accepts VLAs (gcc accepts
// them in all sorts of strange places).
if (!VerifyOnly)
SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
diag::err_variable_object_no_init)
<< VAT->getSizeExpr()->getSourceRange();
@ -1145,7 +1206,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
if (!maxElementsKnown && elementIndex > maxElements)
maxElements = elementIndex;
}
if (!hadError && DeclType->isIncompleteArrayType()) {
if (!hadError && DeclType->isIncompleteArrayType() && !VerifyOnly) {
// If this is an incomplete array type, the actual type needs to
// be calculated here.
llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
@ -1189,11 +1250,13 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
FlexArrayDiag = diag::ext_flexible_array_init;
}
if (!VerifyOnly) {
SemaRef.Diag(InitExpr->getSourceRange().getBegin(),
FlexArrayDiag)
<< InitExpr->getSourceRange().getBegin();
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
<< Field;
}
return FlexArrayDiag != diag::ext_flexible_array_init;
}
@ -1217,6 +1280,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
if (DeclType->isUnionType() && IList->getNumInits() == 0) {
if (!VerifyOnly) {
// Value-initialize the first named member of the union.
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
for (RecordDecl::field_iterator FieldEnd = RD->field_end();
@ -1226,6 +1290,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
break;
}
}
}
return;
}
@ -1283,8 +1348,13 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
// Make sure we can use this declaration.
if (SemaRef.DiagnoseUseOfDecl(*Field,
IList->getInit(Index)->getLocStart())) {
bool InvalidUse;
if (VerifyOnly)
InvalidUse = !SemaRef.CanUseDecl(*Field);
else
InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field,
IList->getInit(Index)->getLocStart());
if (InvalidUse) {
++Index;
++Field;
hadError = true;
@ -1297,7 +1367,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
StructuredList, StructuredIndex);
InitializedSomething = true;
if (DeclType->isUnionType()) {
if (DeclType->isUnionType() && !VerifyOnly) {
// Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field);
}
@ -1306,8 +1376,9 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
// Emit warnings for missing struct field initializers.
if (InitializedSomething && CheckForMissingFields && Field != FieldEnd &&
!Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) {
if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
Field != FieldEnd && !Field->getType()->isIncompleteArrayType() &&
!DeclType->isUnionType()) {
// It is possible we have one or more unnamed bitfields remaining.
// Find first (if any) named field and emit warning.
for (RecordDecl::field_iterator it = Field, end = RD->field_end();
@ -1388,6 +1459,18 @@ static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
return 0;
}
static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef,
DesignatedInitExpr *DIE) {
unsigned NumIndexExprs = DIE->getNumSubExprs() - 1;
SmallVector<Expr*, 4> IndexExprs(NumIndexExprs);
for (unsigned I = 0; I < NumIndexExprs; ++I)
IndexExprs[I] = DIE->getSubExpr(I + 1);
return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators_begin(),
DIE->size(), IndexExprs.data(),
NumIndexExprs, DIE->getEqualOrColonLoc(),
DIE->usesGNUSyntax(), DIE->getInit());
}
/// @brief Check the well-formedness of a C99 designated initializer.
///
/// Determines whether the designated initializer @p DIE, which
@ -1458,11 +1541,12 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
return hadError && !prevHadError;
}
DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
bool IsFirstDesignator = (DesigIdx == 0);
if (!VerifyOnly) {
assert((IsFirstDesignator || StructuredList) &&
"Need a non-designated initializer list to start from");
DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
// Determine the structural initializer list that corresponds to the
// current subobject.
StructuredList = IsFirstDesignator? SyntacticToSemantic[IList]
@ -1471,6 +1555,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
SourceRange(D->getStartLocation(),
DIE->getSourceRange().getEnd()));
assert(StructuredList && "Expected a structured initializer list");
}
if (D->isFieldDesignator()) {
// C99 6.7.8p7:
@ -1487,6 +1572,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
SourceLocation Loc = D->getDotLoc();
if (Loc.isInvalid())
Loc = D->getFieldLoc();
if (!VerifyOnly)
SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
<< SemaRef.getLangOptions().CPlusPlus << CurrentObjectType;
++Index;
@ -1511,6 +1597,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (!KnownField && Field->isAnonymousStructOrUnion()) {
if (IndirectFieldDecl *IF =
FindIndirectFieldDesignator(*Field, FieldName)) {
// In verify mode, don't modify the original.
if (VerifyOnly)
DIE = CloneDesignatedInitExpr(SemaRef, DIE);
ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF);
D = DIE->getDesignator(DesigIdx);
break;
@ -1525,6 +1614,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
}
if (Field == FieldEnd) {
if (VerifyOnly)
return true; // No typo correction when just trying this out.
// There was no normal field in the struct with the designated
// name. Perform another lookup for this name, which may find
// something that we can't designate (e.g., a member function),
@ -1594,15 +1686,22 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// the initializer list.
if (RT->getDecl()->isUnion()) {
FieldIndex = 0;
if (!VerifyOnly)
StructuredList->setInitializedFieldInUnion(*Field);
}
// Make sure we can use this declaration.
if (SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc())) {
bool InvalidUse;
if (VerifyOnly)
InvalidUse = !SemaRef.CanUseDecl(*Field);
else
InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc());
if (InvalidUse) {
++Index;
return true;
}
if (!VerifyOnly) {
// Update the designator with the field declaration.
D->setField(*Field);
@ -1610,6 +1709,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// for a subobject corresponding to this field.
if (FieldIndex >= StructuredList->getNumInits())
StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);
}
// This designator names a flexible array member.
if (Field->getType()->isIncompleteArrayType()) {
@ -1617,6 +1717,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if ((DesigIdx + 1) != DIE->size()) {
// We can't designate an object within the flexible array
// member (because GCC doesn't allow it).
if (!VerifyOnly) {
DesignatedInitExpr::Designator *NextD
= DIE->getDesignator(DesigIdx + 1);
SemaRef.Diag(NextD->getStartLocation(),
@ -1625,17 +1726,20 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
DIE->getSourceRange().getEnd());
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
<< *Field;
}
Invalid = true;
}
if (!hadError && !isa<InitListExpr>(DIE->getInit()) &&
!isa<StringLiteral>(DIE->getInit())) {
// The initializer is not an initializer list.
if (!VerifyOnly) {
SemaRef.Diag(DIE->getInit()->getSourceRange().getBegin(),
diag::err_flexible_array_init_needs_braces)
<< DIE->getInit()->getSourceRange();
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
<< *Field;
}
Invalid = true;
}
@ -1729,6 +1833,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// [ constant-expression ... constant-expression ]
const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType);
if (!AT) {
if (!VerifyOnly)
SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
<< CurrentObjectType;
++Index;
@ -1756,7 +1861,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// elements with something that has a side effect, so codegen can emit an
// "error unsupported" error instead of miscompiling the app.
if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&&
DIE->getInit()->HasSideEffects(SemaRef.Context))
DIE->getInit()->HasSideEffects(SemaRef.Context) && !VerifyOnly)
FullyStructuredList->sawArrayRangeDesignator();
}
@ -1769,6 +1874,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
= DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
if (DesignatedEndIndex >= MaxElements) {
if (VerifyOnly)
SemaRef.Diag(IndexExpr->getSourceRange().getBegin(),
diag::err_array_designator_too_large)
<< DesignatedEndIndex.toString(10) << MaxElements.toString(10)
@ -1791,7 +1897,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Make sure that our non-designated initializer list has space
// for a subobject corresponding to this array element.
if (DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
if (!VerifyOnly &&
DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
StructuredList->resizeInits(SemaRef.Context,
DesignatedEndIndex.getZExtValue() + 1);
@ -1851,6 +1958,8 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
InitListExpr *StructuredList,
unsigned StructuredIndex,
SourceRange InitRange) {
if (VerifyOnly)
return 0; // No structured list in verification-only mode.
Expr *ExistingInit = 0;
if (!StructuredList)
ExistingInit = SyntacticToSemantic[IList];
@ -2628,47 +2737,33 @@ static void TryListInitialization(Sema &S,
const InitializationKind &Kind,
InitListExpr *InitList,
InitializationSequence &Sequence) {
// FIXME: We only perform rudimentary checking of list
// initializations at this point, then assume that any list
// initialization of an array, aggregate, or scalar will be
// well-formed. When we actually "perform" list initialization, we'll
// do all of the necessary checking. C++0x initializer lists will
// force us to perform more checking here.
QualType DestType = Entity.getType();
// C++ [dcl.init]p13:
// If T is a scalar type, then a declaration of the form
//
// T x = { a };
//
// is equivalent to
//
// T x = a;
if (DestType->isAnyComplexType()) {
// We allow more than 1 init for complex types in some cases, even though
// they are scalar.
} else if (DestType->isScalarType()) {
if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) {
// C++ doesn't allow scalar initialization with more than one argument.
// But C99 complex numbers are scalars and it makes sense there.
if (S.getLangOptions().CPlusPlus && DestType->isScalarType() &&
!DestType->isAnyComplexType() && InitList->getNumInits() > 1) {
Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
return;
}
// Assume scalar initialization from a single value works.
} else if (DestType->isAggregateType()) {
// Assume aggregate initialization works.
} else if (DestType->isVectorType()) {
// Assume vector initialization works.
} else if (DestType->isReferenceType()) {
// FIXME: C++0x defines behavior for this.
// FIXME: C++0x defines behavior for these two cases.
if (DestType->isReferenceType()) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
return;
} else if (DestType->isRecordType()) {
// FIXME: C++0x defines behavior for this
}
if (DestType->isRecordType() && !DestType->isAggregateType()) {
Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
return;
}
// Add a general "list initialization" step.
InitListChecker CheckInitList(S, Entity, InitList,
DestType, /*VerifyOnly=*/true);
if (CheckInitList.HadError()) {
Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
return;
}
// Add the list initialization step with the built init list.
Sequence.AddListInitializationStep(DestType);
}
@ -4504,13 +4599,13 @@ InitializationSequence::Perform(Sema &S,
case SK_ListInitialization: {
InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
QualType Ty = Step->Type;
InitListChecker CheckInitList(S, Entity, InitList,
ResultType ? *ResultType : Ty);
if (CheckInitList.HadError())
InitListChecker PerformInitList(S, Entity, InitList,
ResultType ? *ResultType : Ty, /*VerifyOnly=*/false);
if (PerformInitList.HadError())
return ExprError();
CurInit.release();
CurInit = S.Owned(CheckInitList.getFullyStructuredList());
CurInit = S.Owned(PerformInitList.getFullyStructuredList());
break;
}
@ -5022,8 +5117,16 @@ bool InitializationSequence::Diagnose(Sema &S,
diag::err_init_incomplete_type);
break;
case FK_ListInitializationFailed:
assert(false && "Failed list initialization not yet handled.");
case FK_ListInitializationFailed: {
// Run the init list checker again to emit diagnostics.
InitListExpr* InitList = cast<InitListExpr>(Args[0]);
QualType DestType = Entity.getType();
InitListChecker DiagnoseInitList(S, Entity, InitList,
DestType, /*VerifyOnly=*/false);
assert(DiagnoseInitList.HadError() &&
"Inconsistent init list check result.");
break;
}
}
PrintInitLocationNote(S, Entity);
@ -5120,7 +5223,7 @@ void InitializationSequence::dump(raw_ostream &OS) const {
break;
case FK_ListInitializationFailed:
OS << "list initialization failed";
OS << "list initialization checker failure";
}
OS << '\n';
return;

Просмотреть файл

@ -909,27 +909,31 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType,
/// explicit user-defined conversions are permitted.
ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action, bool AllowExplicit) {
AssignmentAction Action, bool AllowExplicit,
bool Diagnose) {
ImplicitConversionSequence ICS;
return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS);
return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS,
Diagnose);
}
ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action, bool AllowExplicit,
ImplicitConversionSequence& ICS) {
ImplicitConversionSequence& ICS,
bool Diagnose) {
// Objective-C ARC: Determine whether we will allow the writeback conversion.
bool AllowObjCWritebackConversion
= getLangOptions().ObjCAutoRefCount &&
(Action == AA_Passing || Action == AA_Sending);
ICS = clang::TryImplicitConversion(*this, From, ToType,
/*SuppressUserConversions=*/false,
AllowExplicit,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
AllowObjCWritebackConversion);
if (!Diagnose && ICS.isFailure())
return ExprError();
return PerformImplicitConversion(From, ToType, ICS, Action);
}