2008-05-02 06:18:59 +08:00
|
|
|
//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2011-09-25 01:47:39 +08:00
|
|
|
// This file implements semantic analysis for initializers.
|
2009-02-25 06:27:37 +08:00
|
|
|
//
|
2008-05-02 06:18:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-08-21 02:27:03 +08:00
|
|
|
#include "clang/Sema/Designator.h"
|
2010-08-13 04:07:10 +08:00
|
|
|
#include "clang/Sema/Initialization.h"
|
|
|
|
#include "clang/Sema/Lookup.h"
|
2010-08-26 06:03:47 +08:00
|
|
|
#include "clang/Sema/SemaInternal.h"
|
2010-03-07 12:17:15 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2008-05-02 06:18:59 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2010-08-24 15:21:54 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2009-05-28 00:10:08 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2009-02-25 07:10:27 +08:00
|
|
|
#include "clang/AST/ExprObjC.h"
|
2009-12-22 23:35:07 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2009-12-10 07:02:17 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2011-07-27 07:20:30 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-01-29 08:45:39 +08:00
|
|
|
#include <map>
|
2009-01-22 08:58:24 +08:00
|
|
|
using namespace clang;
|
2008-05-02 06:18:59 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Sema Initialization Checking
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-02-21 15:22:22 +08:00
|
|
|
static Expr *IsStringInit(Expr *Init, const ArrayType *AT,
|
|
|
|
ASTContext &Context) {
|
2009-05-30 02:22:49 +08:00
|
|
|
if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
|
|
|
|
return 0;
|
|
|
|
|
2009-02-27 07:26:43 +08:00
|
|
|
// See if this is a string literal or @encode.
|
|
|
|
Init = Init->IgnoreParens();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 07:26:43 +08:00
|
|
|
// Handle @encode, which is a narrow string.
|
|
|
|
if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType())
|
|
|
|
return Init;
|
|
|
|
|
|
|
|
// Otherwise we can only handle string literals.
|
|
|
|
StringLiteral *SL = dyn_cast<StringLiteral>(Init);
|
2009-02-27 07:42:47 +08:00
|
|
|
if (SL == 0) return 0;
|
2009-05-31 18:54:53 +08:00
|
|
|
|
|
|
|
QualType ElemTy = Context.getCanonicalType(AT->getElementType());
|
2011-07-27 13:40:30 +08:00
|
|
|
|
|
|
|
switch (SL->getKind()) {
|
|
|
|
case StringLiteral::Ascii:
|
|
|
|
case StringLiteral::UTF8:
|
|
|
|
// char array can be initialized with a narrow string.
|
|
|
|
// Only allow char x[] = "foo"; not char x[] = L"foo";
|
2009-05-31 18:54:53 +08:00
|
|
|
return ElemTy->isCharType() ? Init : 0;
|
2011-07-27 13:40:30 +08:00
|
|
|
case StringLiteral::UTF16:
|
|
|
|
return ElemTy->isChar16Type() ? Init : 0;
|
|
|
|
case StringLiteral::UTF32:
|
|
|
|
return ElemTy->isChar32Type() ? Init : 0;
|
|
|
|
case StringLiteral::Wide:
|
|
|
|
// wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with
|
|
|
|
// correction from DR343): "An array with element type compatible with a
|
|
|
|
// qualified or unqualified version of wchar_t may be initialized by a wide
|
|
|
|
// string literal, optionally enclosed in braces."
|
|
|
|
if (Context.typesAreCompatible(Context.getWCharType(),
|
|
|
|
ElemTy.getUnqualifiedType()))
|
|
|
|
return Init;
|
2009-02-27 07:26:43 +08:00
|
|
|
|
2011-07-27 13:40:30 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-27 13:40:30 +08:00
|
|
|
llvm_unreachable("missed a StringLiteral kind?");
|
2009-02-25 06:27:37 +08:00
|
|
|
}
|
|
|
|
|
2011-02-21 15:22:22 +08:00
|
|
|
static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) {
|
|
|
|
const ArrayType *arrayType = Context.getAsArrayType(declType);
|
|
|
|
if (!arrayType) return 0;
|
|
|
|
|
|
|
|
return IsStringInit(init, arrayType, Context);
|
|
|
|
}
|
|
|
|
|
2011-02-21 15:57:55 +08:00
|
|
|
static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
|
|
|
|
Sema &S) {
|
2009-02-25 07:10:27 +08:00
|
|
|
// Get the length of the string as parsed.
|
|
|
|
uint64_t StrLength =
|
|
|
|
cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue();
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// C99 6.7.8p14. We have an array of character type with unknown size
|
2009-02-25 06:27:37 +08:00
|
|
|
// being initialized to a string literal.
|
|
|
|
llvm::APSInt ConstVal(32);
|
2009-02-25 07:01:39 +08:00
|
|
|
ConstVal = StrLength;
|
2009-02-25 06:27:37 +08:00
|
|
|
// Return a new array type (C99 6.7.8p22).
|
2009-10-16 08:14:28 +08:00
|
|
|
DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
|
|
|
|
ConstVal,
|
|
|
|
ArrayType::Normal, 0);
|
2009-02-25 07:01:39 +08:00
|
|
|
return;
|
2009-02-25 06:27:37 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 02:22:49 +08:00
|
|
|
const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-04-11 08:23:45 +08:00
|
|
|
// We have an array of character type with known size. However,
|
2009-05-30 02:22:49 +08:00
|
|
|
// the size may be smaller or larger than the string we are initializing.
|
|
|
|
// FIXME: Avoid truncation for 64-bit length strings.
|
2011-04-11 08:23:45 +08:00
|
|
|
if (S.getLangOptions().CPlusPlus) {
|
2011-04-14 08:41:11 +08:00
|
|
|
if (StringLiteral *SL = dyn_cast<StringLiteral>(Str)) {
|
|
|
|
// For Pascal strings it's OK to strip off the terminating null character,
|
|
|
|
// so the example below is valid:
|
|
|
|
//
|
|
|
|
// unsigned char a[2] = "\pa";
|
|
|
|
if (SL->isPascal())
|
|
|
|
StrLength--;
|
|
|
|
}
|
|
|
|
|
2011-04-11 08:23:45 +08:00
|
|
|
// [dcl.init.string]p2
|
|
|
|
if (StrLength > CAT->getSize().getZExtValue())
|
|
|
|
S.Diag(Str->getSourceRange().getBegin(),
|
|
|
|
diag::err_initializer_string_for_char_array_too_long)
|
|
|
|
<< Str->getSourceRange();
|
|
|
|
} else {
|
|
|
|
// C99 6.7.8p14.
|
|
|
|
if (StrLength-1 > CAT->getSize().getZExtValue())
|
|
|
|
S.Diag(Str->getSourceRange().getBegin(),
|
|
|
|
diag::warn_initializer_string_for_char_array_too_long)
|
|
|
|
<< Str->getSourceRange();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 02:22:49 +08:00
|
|
|
// Set the type to the actual size that we are initializing. If we have
|
|
|
|
// something like:
|
|
|
|
// char x[1] = "foo";
|
|
|
|
// then this will set the string literal's type to char[1].
|
|
|
|
Str->setType(DeclT);
|
2009-02-25 06:27:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Semantic checking for initializer lists.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-01-29 09:05:33 +08:00
|
|
|
/// @brief Semantic checking for initializer lists.
|
|
|
|
///
|
|
|
|
/// The InitListChecker class contains a set of routines that each
|
|
|
|
/// handle the initialization of a certain kind of entity, e.g.,
|
|
|
|
/// arrays, vectors, struct/union types, scalars, etc. The
|
|
|
|
/// InitListChecker itself performs a recursive walk of the subobject
|
|
|
|
/// structure of the type to be initialized, while stepping through
|
|
|
|
/// the initializer list one element at a time. The IList and Index
|
|
|
|
/// parameters to each of the Check* routines contain the active
|
|
|
|
/// (syntactic) initializer list and the index into that initializer
|
|
|
|
/// list that represents the current initializer. Each routine is
|
|
|
|
/// responsible for moving that Index forward as it consumes elements.
|
|
|
|
///
|
|
|
|
/// Each Check* routine also has a StructuredList/StructuredIndex
|
2011-01-28 03:55:10 +08:00
|
|
|
/// arguments, which contains the current "structured" (semantic)
|
2009-01-29 09:05:33 +08:00
|
|
|
/// initializer list and the index into that initializer list where we
|
|
|
|
/// are copying initializers as we map them over to the semantic
|
|
|
|
/// list. Once we have completed our recursive walk of the subobject
|
|
|
|
/// structure, we will have constructed a full semantic initializer
|
|
|
|
/// list.
|
|
|
|
///
|
|
|
|
/// C99 designators cause changes in the initializer list traversal,
|
|
|
|
/// because they make the initialization "jump" into a specific
|
|
|
|
/// subobject and then continue the initialization from that
|
|
|
|
/// point. CheckDesignatedInitializer() recursively steps into the
|
|
|
|
/// designated subobject and manages backing out the recursion to
|
|
|
|
/// initialize the subobjects after the one designated.
|
2009-02-25 06:48:58 +08:00
|
|
|
namespace {
|
2009-01-29 08:45:39 +08:00
|
|
|
class InitListChecker {
|
2009-02-25 06:50:46 +08:00
|
|
|
Sema &SemaRef;
|
2009-01-29 08:45:39 +08:00
|
|
|
bool hadError;
|
2011-09-25 01:48:00 +08:00
|
|
|
bool VerifyOnly; // no diagnostics, no structure building
|
2009-01-29 08:45:39 +08:00
|
|
|
std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
|
|
|
|
InitListExpr *FullyStructuredList;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckImplicitInitList(const InitializedEntity &Entity,
|
2010-01-24 04:47:59 +08:00
|
|
|
InitListExpr *ParentIList, QualType T,
|
2009-01-29 09:05:33 +08:00
|
|
|
unsigned &Index, InitListExpr *StructuredList,
|
2011-08-24 04:17:13 +08:00
|
|
|
unsigned &StructuredIndex);
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckExplicitInitList(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList, QualType &T,
|
2009-01-29 09:05:33 +08:00
|
|
|
unsigned &Index, InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject = false);
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckListElementTypes(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList, QualType &DeclType,
|
2009-09-09 23:08:12 +08:00
|
|
|
bool SubobjectIsDesignatorContext,
|
2009-01-29 08:45:39 +08:00
|
|
|
unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject = false);
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckSubElementType(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList, QualType ElemType,
|
2009-01-29 08:45:39 +08:00
|
|
|
unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2011-09-20 07:17:44 +08:00
|
|
|
void CheckComplexType(const InitializedEntity &Entity,
|
|
|
|
InitListExpr *IList, QualType DeclType,
|
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckScalarType(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList, QualType DeclType,
|
2009-01-29 08:45:39 +08:00
|
|
|
unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckReferenceType(const InitializedEntity &Entity,
|
|
|
|
InitListExpr *IList, QualType DeclType,
|
2009-01-31 06:09:00 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckVectorType(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList, QualType DeclType, unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckStructUnionTypes(const InitializedEntity &Entity,
|
2010-01-24 04:20:40 +08:00
|
|
|
InitListExpr *IList, QualType DeclType,
|
2009-09-09 23:08:12 +08:00
|
|
|
RecordDecl::field_iterator Field,
|
2009-01-29 08:45:39 +08:00
|
|
|
bool SubobjectIsDesignatorContext, unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject = false);
|
2010-01-24 07:23:01 +08:00
|
|
|
void CheckArrayType(const InitializedEntity &Entity,
|
2010-01-24 04:13:41 +08:00
|
|
|
InitListExpr *IList, QualType &DeclType,
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::APSInt elementIndex,
|
2009-01-29 08:45:39 +08:00
|
|
|
bool SubobjectIsDesignatorContext, unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2010-01-24 07:23:01 +08:00
|
|
|
bool CheckDesignatedInitializer(const InitializedEntity &Entity,
|
2010-01-24 06:49:02 +08:00
|
|
|
InitListExpr *IList, DesignatedInitExpr *DIE,
|
2009-04-15 12:56:10 +08:00
|
|
|
unsigned DesigIdx,
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType &CurrentObjectType,
|
2009-01-29 08:45:39 +08:00
|
|
|
RecordDecl::field_iterator *NextField,
|
|
|
|
llvm::APSInt *NextElementIndex,
|
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
bool FinishSubobjectInit,
|
|
|
|
bool TopLevelObject);
|
2009-01-29 08:45:39 +08:00
|
|
|
InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
|
|
|
|
QualType CurrentObjectType,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned StructuredIndex,
|
|
|
|
SourceRange InitRange);
|
2009-01-29 09:05:33 +08:00
|
|
|
void UpdateStructuredListElement(InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex,
|
2009-01-29 08:45:39 +08:00
|
|
|
Expr *expr);
|
|
|
|
int numArrayElements(QualType DeclType);
|
|
|
|
int numStructUnionElements(QualType DeclType);
|
2009-01-31 06:09:00 +08:00
|
|
|
|
2009-12-22 08:05:34 +08:00
|
|
|
void FillInValueInitForField(unsigned Init, FieldDecl *Field,
|
|
|
|
const InitializedEntity &ParentEntity,
|
|
|
|
InitListExpr *ILE, bool &RequiresSecondPass);
|
2009-12-16 14:35:08 +08:00
|
|
|
void FillInValueInitializations(const InitializedEntity &Entity,
|
|
|
|
InitListExpr *ILE, bool &RequiresSecondPass);
|
2011-08-24 06:24:57 +08:00
|
|
|
bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
|
|
|
|
Expr *InitExpr, FieldDecl *Field,
|
|
|
|
bool TopLevelObject);
|
2009-01-29 08:45:39 +08:00
|
|
|
public:
|
2009-12-16 14:35:08 +08:00
|
|
|
InitListChecker(Sema &S, const InitializedEntity &Entity,
|
2011-09-25 01:48:00 +08:00
|
|
|
InitListExpr *IL, QualType &T, bool VerifyOnly);
|
2009-01-29 08:45:39 +08:00
|
|
|
bool HadError() { return hadError; }
|
|
|
|
|
|
|
|
// @brief Retrieves the fully-structured initializer list used for
|
|
|
|
// semantic analysis and code generation.
|
|
|
|
InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
|
|
|
|
};
|
2009-02-25 06:48:58 +08:00
|
|
|
} // end anonymous namespace
|
2009-01-29 13:10:57 +08:00
|
|
|
|
2009-12-22 08:05:34 +08:00
|
|
|
void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
|
|
|
|
const InitializedEntity &ParentEntity,
|
2011-01-27 15:10:08 +08:00
|
|
|
InitListExpr *ILE,
|
2009-12-22 08:05:34 +08:00
|
|
|
bool &RequiresSecondPass) {
|
|
|
|
SourceLocation Loc = ILE->getSourceRange().getBegin();
|
|
|
|
unsigned NumInits = ILE->getNumInits();
|
2011-01-27 15:10:08 +08:00
|
|
|
InitializedEntity MemberEntity
|
2009-12-22 08:05:34 +08:00
|
|
|
= InitializedEntity::InitializeMember(Field, &ParentEntity);
|
|
|
|
if (Init >= NumInits || !ILE->getInit(Init)) {
|
|
|
|
// FIXME: We probably don't need to handle references
|
|
|
|
// specially here, since value-initialization of references is
|
|
|
|
// handled in InitializationSequence.
|
|
|
|
if (Field->getType()->isReferenceType()) {
|
|
|
|
// C++ [dcl.init.aggr]p9:
|
|
|
|
// If an incomplete or empty initializer-list leaves a
|
|
|
|
// member of reference type uninitialized, the program is
|
|
|
|
// ill-formed.
|
|
|
|
SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
|
|
|
|
<< Field->getType()
|
|
|
|
<< ILE->getSyntacticForm()->getSourceRange();
|
|
|
|
SemaRef.Diag(Field->getLocation(),
|
|
|
|
diag::note_uninit_reference_member);
|
|
|
|
hadError = true;
|
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-22 08:05:34 +08:00
|
|
|
InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
|
|
|
|
true);
|
|
|
|
InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
|
|
|
|
if (!InitSeq) {
|
|
|
|
InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
|
|
|
|
hadError = true;
|
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult MemberInit
|
2010-08-27 07:41:50 +08:00
|
|
|
= InitSeq.Perform(SemaRef, MemberEntity, Kind, MultiExprArg());
|
2009-12-22 08:05:34 +08:00
|
|
|
if (MemberInit.isInvalid()) {
|
|
|
|
hadError = true;
|
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-22 08:05:34 +08:00
|
|
|
if (hadError) {
|
|
|
|
// Do nothing
|
|
|
|
} else if (Init < NumInits) {
|
|
|
|
ILE->setInit(Init, MemberInit.takeAs<Expr>());
|
2011-06-05 21:59:11 +08:00
|
|
|
} else if (InitSeq.isConstructorInitialization()) {
|
2009-12-22 08:05:34 +08:00
|
|
|
// Value-initialization requires a constructor call, so
|
|
|
|
// extend the initializer list to include the constructor
|
|
|
|
// call and make a note that we'll need to take another pass
|
|
|
|
// through the initializer list.
|
2010-04-14 07:39:13 +08:00
|
|
|
ILE->updateInit(SemaRef.Context, Init, MemberInit.takeAs<Expr>());
|
2009-12-22 08:05:34 +08:00
|
|
|
RequiresSecondPass = true;
|
|
|
|
}
|
|
|
|
} else if (InitListExpr *InnerILE
|
|
|
|
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
|
2011-01-27 15:10:08 +08:00
|
|
|
FillInValueInitializations(MemberEntity, InnerILE,
|
|
|
|
RequiresSecondPass);
|
2009-12-22 08:05:34 +08:00
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
/// Recursively replaces NULL values within the given initializer list
|
|
|
|
/// with expressions that perform value-initialization of the
|
|
|
|
/// appropriate type.
|
2011-01-27 15:10:08 +08:00
|
|
|
void
|
2009-12-16 14:35:08 +08:00
|
|
|
InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
|
|
|
|
InitListExpr *ILE,
|
|
|
|
bool &RequiresSecondPass) {
|
2009-09-09 23:08:12 +08:00
|
|
|
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
|
2009-01-31 06:09:00 +08:00
|
|
|
"Should not have void type");
|
2009-02-03 01:43:21 +08:00
|
|
|
SourceLocation Loc = ILE->getSourceRange().getBegin();
|
|
|
|
if (ILE->getSyntacticForm())
|
|
|
|
Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
|
2009-12-22 08:05:34 +08:00
|
|
|
if (RType->getDecl()->isUnion() &&
|
|
|
|
ILE->getInitializedFieldInUnion())
|
|
|
|
FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
|
|
|
|
Entity, ILE, RequiresSecondPass);
|
|
|
|
else {
|
|
|
|
unsigned Init = 0;
|
|
|
|
for (RecordDecl::field_iterator
|
|
|
|
Field = RType->getDecl()->field_begin(),
|
|
|
|
FieldEnd = RType->getDecl()->field_end();
|
|
|
|
Field != FieldEnd; ++Field) {
|
|
|
|
if (Field->isUnnamedBitfield())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (hadError)
|
2009-02-03 01:43:21 +08:00
|
|
|
return;
|
|
|
|
|
2009-12-22 08:05:34 +08:00
|
|
|
FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
|
|
|
|
if (hadError)
|
2009-12-16 14:35:08 +08:00
|
|
|
return;
|
|
|
|
|
2009-12-22 08:05:34 +08:00
|
|
|
++Init;
|
|
|
|
|
|
|
|
// Only look at the first initialization of a union.
|
|
|
|
if (RType->getDecl()->isUnion())
|
|
|
|
break;
|
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
|
|
|
|
QualType ElementType;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-16 14:35:08 +08:00
|
|
|
InitializedEntity ElementEntity = Entity;
|
2009-02-03 01:43:21 +08:00
|
|
|
unsigned NumInits = ILE->getNumInits();
|
|
|
|
unsigned NumElements = NumInits;
|
2009-02-25 06:50:46 +08:00
|
|
|
if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
|
2009-01-29 05:54:33 +08:00
|
|
|
ElementType = AType->getElementType();
|
2009-02-03 01:43:21 +08:00
|
|
|
if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
|
|
|
|
NumElements = CAType->getSize().getZExtValue();
|
2011-01-27 15:10:08 +08:00
|
|
|
ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
|
2009-12-16 14:35:08 +08:00
|
|
|
0, Entity);
|
2009-09-22 07:43:11 +08:00
|
|
|
} else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
|
2009-01-29 05:54:33 +08:00
|
|
|
ElementType = VType->getElementType();
|
2009-02-03 01:43:21 +08:00
|
|
|
NumElements = VType->getNumElements();
|
2011-01-27 15:10:08 +08:00
|
|
|
ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
|
2009-12-16 14:35:08 +08:00
|
|
|
0, Entity);
|
2009-09-09 23:08:12 +08:00
|
|
|
} else
|
2009-01-29 05:54:33 +08:00
|
|
|
ElementType = ILE->getType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-02-03 01:43:21 +08:00
|
|
|
for (unsigned Init = 0; Init != NumElements; ++Init) {
|
2009-12-17 02:50:27 +08:00
|
|
|
if (hadError)
|
|
|
|
return;
|
|
|
|
|
2010-01-23 12:34:47 +08:00
|
|
|
if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement ||
|
|
|
|
ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
|
2009-12-16 14:35:08 +08:00
|
|
|
ElementEntity.setElementIndex(Init);
|
|
|
|
|
2009-02-03 01:43:21 +08:00
|
|
|
if (Init >= NumInits || !ILE->getInit(Init)) {
|
2009-12-16 14:35:08 +08:00
|
|
|
InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
|
|
|
|
true);
|
|
|
|
InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0);
|
|
|
|
if (!InitSeq) {
|
|
|
|
InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0);
|
2009-02-03 01:43:21 +08:00
|
|
|
hadError = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult ElementInit
|
2010-08-27 07:41:50 +08:00
|
|
|
= InitSeq.Perform(SemaRef, ElementEntity, Kind, MultiExprArg());
|
2009-12-16 14:35:08 +08:00
|
|
|
if (ElementInit.isInvalid()) {
|
2009-12-17 02:50:27 +08:00
|
|
|
hadError = true;
|
2009-12-16 14:35:08 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hadError) {
|
|
|
|
// Do nothing
|
|
|
|
} else if (Init < NumInits) {
|
2011-04-22 04:03:38 +08:00
|
|
|
// For arrays, just set the expression used for value-initialization
|
|
|
|
// of the "holes" in the array.
|
|
|
|
if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement)
|
|
|
|
ILE->setArrayFiller(ElementInit.takeAs<Expr>());
|
|
|
|
else
|
|
|
|
ILE->setInit(Init, ElementInit.takeAs<Expr>());
|
2011-04-21 08:27:41 +08:00
|
|
|
} else {
|
|
|
|
// For arrays, just set the expression used for value-initialization
|
|
|
|
// of the rest of elements and exit.
|
|
|
|
if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) {
|
|
|
|
ILE->setArrayFiller(ElementInit.takeAs<Expr>());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-06-05 21:59:11 +08:00
|
|
|
if (InitSeq.isConstructorInitialization()) {
|
2011-04-21 08:27:41 +08:00
|
|
|
// Value-initialization requires a constructor call, so
|
|
|
|
// extend the initializer list to include the constructor
|
|
|
|
// call and make a note that we'll need to take another pass
|
|
|
|
// through the initializer list.
|
|
|
|
ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs<Expr>());
|
|
|
|
RequiresSecondPass = true;
|
|
|
|
}
|
2009-12-16 14:35:08 +08:00
|
|
|
}
|
2009-08-05 05:02:39 +08:00
|
|
|
} else if (InitListExpr *InnerILE
|
2009-12-16 14:35:08 +08:00
|
|
|
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
|
|
|
|
FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass);
|
2009-01-29 05:54:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-29 13:10:57 +08:00
|
|
|
|
2009-12-16 14:35:08 +08:00
|
|
|
InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
|
2011-09-25 01:48:00 +08:00
|
|
|
InitListExpr *IL, QualType &T,
|
|
|
|
bool VerifyOnly)
|
|
|
|
: SemaRef(S), VerifyOnly(VerifyOnly) {
|
2008-05-02 06:18:59 +08:00
|
|
|
hadError = false;
|
2008-05-20 04:00:43 +08:00
|
|
|
|
2008-05-20 03:16:24 +08:00
|
|
|
unsigned newIndex = 0;
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned newStructuredIndex = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
FullyStructuredList
|
2009-03-02 01:12:46 +08:00
|
|
|
= getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
|
2011-01-27 15:10:08 +08:00
|
|
|
CheckExplicitInitList(Entity, IL, T, newIndex,
|
2010-01-24 03:55:29 +08:00
|
|
|
FullyStructuredList, newStructuredIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
/*TopLevelObject=*/true);
|
2008-05-20 04:00:43 +08:00
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!hadError && !VerifyOnly) {
|
2009-12-16 14:35:08 +08:00
|
|
|
bool RequiresSecondPass = false;
|
|
|
|
FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
|
2009-12-17 02:50:27 +08:00
|
|
|
if (RequiresSecondPass && !hadError)
|
2011-01-27 15:10:08 +08:00
|
|
|
FillInValueInitializations(Entity, FullyStructuredList,
|
2009-12-16 14:35:08 +08:00
|
|
|
RequiresSecondPass);
|
|
|
|
}
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int InitListChecker::numArrayElements(QualType DeclType) {
|
2008-05-25 21:22:35 +08:00
|
|
|
// FIXME: use a proper constant
|
|
|
|
int maxElements = 0x7FFFFFFF;
|
2008-08-04 15:31:14 +08:00
|
|
|
if (const ConstantArrayType *CAT =
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Context.getAsConstantArrayType(DeclType)) {
|
2008-05-02 06:18:59 +08:00
|
|
|
maxElements = static_cast<int>(CAT->getSize().getZExtValue());
|
|
|
|
}
|
|
|
|
return maxElements;
|
|
|
|
}
|
|
|
|
|
|
|
|
int InitListChecker::numStructUnionElements(QualType DeclType) {
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
|
2009-01-29 05:54:33 +08:00
|
|
|
int InitializableMembers = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
for (RecordDecl::field_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
Field = structDecl->field_begin(),
|
|
|
|
FieldEnd = structDecl->field_end();
|
2009-01-29 05:54:33 +08:00
|
|
|
Field != FieldEnd; ++Field) {
|
2011-10-11 01:22:13 +08:00
|
|
|
if (!Field->isUnnamedBitfield())
|
2009-01-29 05:54:33 +08:00
|
|
|
++InitializableMembers;
|
|
|
|
}
|
2008-06-10 07:19:58 +08:00
|
|
|
if (structDecl->isUnion())
|
2008-05-25 22:03:31 +08:00
|
|
|
return std::min(InitializableMembers, 1);
|
|
|
|
return InitializableMembers - structDecl->hasFlexibleArrayMember();
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
|
2010-01-24 04:47:59 +08:00
|
|
|
InitListExpr *ParentIList,
|
2009-01-29 05:54:33 +08:00
|
|
|
QualType T, unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2011-08-24 04:17:13 +08:00
|
|
|
unsigned &StructuredIndex) {
|
2008-05-02 06:18:59 +08:00
|
|
|
int maxElements = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-02 06:18:59 +08:00
|
|
|
if (T->isArrayType())
|
|
|
|
maxElements = numArrayElements(T);
|
2010-04-27 05:31:17 +08:00
|
|
|
else if (T->isRecordType())
|
2008-05-02 06:18:59 +08:00
|
|
|
maxElements = numStructUnionElements(T);
|
2008-05-20 03:16:24 +08:00
|
|
|
else if (T->isVectorType())
|
2009-09-22 07:43:11 +08:00
|
|
|
maxElements = T->getAs<VectorType>()->getNumElements();
|
2008-05-02 06:18:59 +08:00
|
|
|
else
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("CheckImplicitInitList(): Illegal type");
|
2008-05-20 03:16:24 +08:00
|
|
|
|
2008-05-25 21:49:22 +08:00
|
|
|
if (maxElements == 0) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
|
|
|
|
diag::err_implicit_empty_initializer);
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
2008-05-25 21:49:22 +08:00
|
|
|
hadError = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Build a structured initializer list corresponding to this subobject.
|
|
|
|
InitListExpr *StructuredSubobjectInitList
|
2009-09-09 23:08:12 +08:00
|
|
|
= getStructuredSubobjectInit(ParentIList, Index, T, StructuredList,
|
|
|
|
StructuredIndex,
|
2009-03-02 01:12:46 +08:00
|
|
|
SourceRange(ParentIList->getInit(Index)->getSourceRange().getBegin(),
|
|
|
|
ParentIList->getSourceRange().getEnd()));
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned StructuredSubobjectInitIndex = 0;
|
|
|
|
|
|
|
|
// Check the element types and build the structural subobject.
|
2009-02-03 01:43:21 +08:00
|
|
|
unsigned StartIndex = Index;
|
2011-01-27 15:10:08 +08:00
|
|
|
CheckListElementTypes(Entity, ParentIList, T,
|
2010-01-24 04:47:59 +08:00
|
|
|
/*SubobjectIsDesignatorContext=*/false, Index,
|
2009-09-09 23:08:12 +08:00
|
|
|
StructuredSubobjectInitList,
|
2011-08-24 04:17:13 +08:00
|
|
|
StructuredSubobjectInitIndex);
|
2009-02-03 01:43:21 +08:00
|
|
|
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly) {
|
|
|
|
StructuredSubobjectInitList->setType(T);
|
|
|
|
|
|
|
|
// Update the structured sub-object initializer so that it's ending
|
|
|
|
// range corresponds with the end of the last initializer it used.
|
|
|
|
if (EndIndex < ParentIList->getNumInits()) {
|
|
|
|
SourceLocation EndLoc
|
|
|
|
= ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
|
|
|
|
StructuredSubobjectInitList->setRBraceLoc(EndLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Warn about missing braces.
|
|
|
|
if (T->isArrayType() || T->isRecordType()) {
|
|
|
|
SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
|
|
|
|
diag::warn_missing_braces)
|
|
|
|
<< StructuredSubobjectInitList->getSourceRange()
|
|
|
|
<< FixItHint::CreateInsertion(
|
|
|
|
StructuredSubobjectInitList->getLocStart(), "{")
|
|
|
|
<< FixItHint::CreateInsertion(
|
|
|
|
SemaRef.PP.getLocForEndOfToken(
|
2011-01-27 15:10:08 +08:00
|
|
|
StructuredSubobjectInitList->getLocEnd()),
|
2011-09-25 01:48:00 +08:00
|
|
|
"}");
|
|
|
|
}
|
2010-03-07 12:17:15 +08:00
|
|
|
}
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList, QualType &T,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject) {
|
2008-05-20 04:00:43 +08:00
|
|
|
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly) {
|
|
|
|
SyntacticToSemantic[IList] = StructuredList;
|
|
|
|
StructuredList->setSyntacticForm(IList);
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
|
2010-01-24 03:55:29 +08:00
|
|
|
Index, StructuredList, StructuredIndex, TopLevelObject);
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly) {
|
|
|
|
QualType ExprTy = T.getNonLValueExprType(SemaRef.Context);
|
|
|
|
IList->setType(ExprTy);
|
|
|
|
StructuredList->setType(ExprTy);
|
|
|
|
}
|
2008-05-25 21:22:35 +08:00
|
|
|
if (hadError)
|
|
|
|
return;
|
2008-05-20 04:00:43 +08:00
|
|
|
|
2008-05-25 21:22:35 +08:00
|
|
|
if (Index < IList->getNumInits()) {
|
2008-05-20 04:00:43 +08:00
|
|
|
// We have leftover initializers
|
2011-09-25 01:48:00 +08:00
|
|
|
if (VerifyOnly) {
|
|
|
|
if (SemaRef.getLangOptions().CPlusPlus ||
|
|
|
|
(SemaRef.getLangOptions().OpenCL &&
|
|
|
|
IList->getType()->isVectorType())) {
|
|
|
|
hadError = true;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-05-30 04:20:05 +08:00
|
|
|
if (StructuredIndex == 1 &&
|
|
|
|
IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) {
|
2009-02-19 06:23:55 +08:00
|
|
|
unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
|
2009-05-30 04:20:05 +08:00
|
|
|
if (SemaRef.getLangOptions().CPlusPlus) {
|
2009-02-19 06:23:55 +08:00
|
|
|
DK = diag::err_excess_initializers_in_char_array_initializer;
|
2009-05-30 04:20:05 +08:00
|
|
|
hadError = true;
|
|
|
|
}
|
2008-05-20 04:12:18 +08:00
|
|
|
// Special-case
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
|
2008-11-19 13:27:50 +08:00
|
|
|
<< IList->getInit(Index)->getSourceRange();
|
2008-05-20 13:25:56 +08:00
|
|
|
} else if (!T->isIncompleteType()) {
|
2009-01-31 06:26:29 +08:00
|
|
|
// Don't complain for incomplete types, since we'll get an error
|
|
|
|
// elsewhere
|
2009-02-05 06:46:25 +08:00
|
|
|
QualType CurrentObjectType = StructuredList->getType();
|
2009-09-09 23:08:12 +08:00
|
|
|
int initKind =
|
2009-02-05 06:46:25 +08:00
|
|
|
CurrentObjectType->isArrayType()? 0 :
|
|
|
|
CurrentObjectType->isVectorType()? 1 :
|
|
|
|
CurrentObjectType->isScalarType()? 2 :
|
|
|
|
CurrentObjectType->isUnionType()? 3 :
|
|
|
|
4;
|
2009-02-19 06:23:55 +08:00
|
|
|
|
|
|
|
unsigned DK = diag::warn_excess_initializers;
|
2009-05-30 04:20:05 +08:00
|
|
|
if (SemaRef.getLangOptions().CPlusPlus) {
|
|
|
|
DK = diag::err_excess_initializers;
|
2009-07-08 05:53:06 +08:00
|
|
|
hadError = true;
|
|
|
|
}
|
|
|
|
if (SemaRef.getLangOptions().OpenCL && initKind == 1) {
|
|
|
|
DK = diag::err_excess_initializers;
|
2009-05-30 04:20:05 +08:00
|
|
|
hadError = true;
|
|
|
|
}
|
2009-02-19 06:23:55 +08:00
|
|
|
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
|
2009-02-05 06:46:25 +08:00
|
|
|
<< initKind << IList->getInit(Index)->getSourceRange();
|
2008-05-20 04:00:43 +08:00
|
|
|
}
|
|
|
|
}
|
2008-05-20 04:20:43 +08:00
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 &&
|
|
|
|
!TopLevelObject)
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
|
2009-04-02 07:51:29 +08:00
|
|
|
<< IList->getSourceRange()
|
2010-04-01 01:46:05 +08:00
|
|
|
<< FixItHint::CreateRemoval(IList->getLocStart())
|
|
|
|
<< FixItHint::CreateRemoval(IList->getLocEnd());
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList,
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType &DeclType,
|
2009-01-23 07:26:18 +08:00
|
|
|
bool SubobjectIsDesignatorContext,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject) {
|
2011-09-20 07:17:44 +08:00
|
|
|
if (DeclType->isAnyComplexType() && SubobjectIsDesignatorContext) {
|
|
|
|
// Explicitly braced initializer for complex type can be real+imaginary
|
|
|
|
// parts.
|
|
|
|
CheckComplexType(Entity, IList, DeclType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
} else if (DeclType->isScalarType()) {
|
2010-01-24 03:55:29 +08:00
|
|
|
CheckScalarType(Entity, IList, DeclType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
2008-05-20 04:00:43 +08:00
|
|
|
} else if (DeclType->isVectorType()) {
|
2011-01-27 15:10:08 +08:00
|
|
|
CheckVectorType(Entity, IList, DeclType, Index,
|
2010-01-24 03:55:29 +08:00
|
|
|
StructuredList, StructuredIndex);
|
2009-01-31 01:31:00 +08:00
|
|
|
} else if (DeclType->isAggregateType()) {
|
|
|
|
if (DeclType->isRecordType()) {
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
|
2010-01-24 04:20:40 +08:00
|
|
|
CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(),
|
2009-01-29 05:54:33 +08:00
|
|
|
SubobjectIsDesignatorContext, Index,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredList, StructuredIndex,
|
|
|
|
TopLevelObject);
|
2009-01-23 07:26:18 +08:00
|
|
|
} else if (DeclType->isArrayType()) {
|
2009-01-24 00:54:12 +08:00
|
|
|
llvm::APSInt Zero(
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
|
2009-01-24 00:54:12 +08:00
|
|
|
false);
|
2011-01-27 15:10:08 +08:00
|
|
|
CheckArrayType(Entity, IList, DeclType, Zero,
|
2010-01-24 04:13:41 +08:00
|
|
|
SubobjectIsDesignatorContext, Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList, StructuredIndex);
|
2009-08-05 05:02:39 +08:00
|
|
|
} else
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Aggregate that isn't a structure or array?!");
|
2008-08-11 00:05:48 +08:00
|
|
|
} else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
|
|
|
|
// This type is invalid, issue a diagnostic.
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
|
|
|
|
<< DeclType;
|
2008-05-20 13:25:56 +08:00
|
|
|
hadError = true;
|
2009-01-31 06:09:00 +08:00
|
|
|
} else if (DeclType->isRecordType()) {
|
|
|
|
// C++ [dcl.init]p14:
|
|
|
|
// [...] If the class is an aggregate (8.5.1), and the initializer
|
|
|
|
// is a brace-enclosed list, see 8.5.1.
|
|
|
|
//
|
|
|
|
// Note: 8.5.1 is handled below; here, we diagnose the case where
|
|
|
|
// 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.
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
|
|
|
|
<< DeclType << IList->getSourceRange();
|
2009-01-31 06:09:00 +08:00
|
|
|
hadError = true;
|
|
|
|
} else if (DeclType->isReferenceType()) {
|
2010-01-24 07:23:01 +08:00
|
|
|
CheckReferenceType(Entity, IList, DeclType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
2010-05-15 19:32:37 +08:00
|
|
|
} else if (DeclType->isObjCObjectType()) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class)
|
|
|
|
<< DeclType;
|
2010-05-04 02:24:37 +08:00
|
|
|
hadError = true;
|
2008-05-02 06:18:59 +08:00
|
|
|
} else {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
|
|
|
|
<< DeclType;
|
2010-05-04 02:24:37 +08:00
|
|
|
hadError = true;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList,
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType ElemType,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2009-01-29 08:39:20 +08:00
|
|
|
Expr *expr = IList->getInit(Index);
|
2008-05-20 04:00:43 +08:00
|
|
|
if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
|
|
|
|
unsigned newIndex = 0;
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned newStructuredIndex = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
InitListExpr *newStructuredList
|
2009-01-29 05:54:33 +08:00
|
|
|
= getStructuredSubobjectInit(IList, Index, ElemType,
|
|
|
|
StructuredList, StructuredIndex,
|
|
|
|
SubInitList->getSourceRange());
|
2010-01-24 03:55:29 +08:00
|
|
|
CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex,
|
2009-01-29 05:54:33 +08:00
|
|
|
newStructuredList, newStructuredIndex);
|
|
|
|
++StructuredIndex;
|
|
|
|
++Index;
|
2011-02-21 15:57:55 +08:00
|
|
|
return;
|
2008-05-20 04:00:43 +08:00
|
|
|
} else if (ElemType->isScalarType()) {
|
2011-02-21 15:57:55 +08:00
|
|
|
return CheckScalarType(Entity, IList, ElemType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
2009-01-31 06:09:00 +08:00
|
|
|
} else if (ElemType->isReferenceType()) {
|
2011-02-21 15:57:55 +08:00
|
|
|
return CheckReferenceType(Entity, IList, ElemType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
}
|
2009-01-31 06:09:00 +08:00
|
|
|
|
2011-02-21 15:57:55 +08:00
|
|
|
if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) {
|
|
|
|
// arrayType can be incomplete if we're initializing a flexible
|
|
|
|
// array member. There's nothing we can do with the completed
|
|
|
|
// type here, though.
|
2009-01-31 06:09:00 +08:00
|
|
|
|
2011-02-21 15:57:55 +08:00
|
|
|
if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) {
|
2011-09-27 03:09:09 +08:00
|
|
|
if (!VerifyOnly) {
|
|
|
|
CheckStringInit(Str, ElemType, arrayType, SemaRef);
|
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
|
|
|
|
}
|
2011-02-21 15:57:55 +08:00
|
|
|
++Index;
|
|
|
|
return;
|
2009-01-31 06:09:00 +08:00
|
|
|
}
|
|
|
|
|
2011-02-21 15:57:55 +08:00
|
|
|
// Fall through for subaggregate initialization.
|
|
|
|
|
|
|
|
} else if (SemaRef.getLangOptions().CPlusPlus) {
|
2009-01-31 06:09:00 +08:00
|
|
|
// C++ [dcl.init.aggr]p12:
|
2011-02-21 15:57:55 +08:00
|
|
|
// All implicit type conversions (clause 4) are considered when
|
2011-09-25 01:47:39 +08:00
|
|
|
// initializing the aggregate member with an initializer from
|
2011-02-21 15:57:55 +08:00
|
|
|
// an initializer-list. If the initializer can initialize a
|
|
|
|
// member, the member is initialized. [...]
|
|
|
|
|
|
|
|
// FIXME: Better EqualLoc?
|
|
|
|
InitializationKind Kind =
|
|
|
|
InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
|
|
|
|
InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
|
|
|
|
|
|
|
|
if (Seq) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly) {
|
|
|
|
ExprResult Result =
|
|
|
|
Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
|
|
|
|
if (Result.isInvalid())
|
|
|
|
hadError = true;
|
|
|
|
|
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex,
|
|
|
|
Result.takeAs<Expr>());
|
|
|
|
}
|
2011-02-21 15:57:55 +08:00
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through for subaggregate initialization
|
|
|
|
} else {
|
|
|
|
// C99 6.7.8p13:
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2011-02-21 15:57:55 +08:00
|
|
|
// The initializer for a structure or union object that has
|
|
|
|
// automatic storage duration shall be either an initializer
|
|
|
|
// list as described below, or a single expression that has
|
|
|
|
// compatible structure or union type. In the latter case, the
|
|
|
|
// initial value of the object, including unnamed members, is
|
|
|
|
// that of the expression.
|
2011-04-09 02:41:53 +08:00
|
|
|
ExprResult ExprRes = SemaRef.Owned(expr);
|
2011-02-21 15:57:55 +08:00
|
|
|
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
|
2011-09-25 01:48:00 +08:00
|
|
|
SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
|
|
|
|
!VerifyOnly)
|
2011-02-21 15:57:55 +08:00
|
|
|
== Sema::Compatible) {
|
2011-04-09 02:41:53 +08:00
|
|
|
if (ExprRes.isInvalid())
|
|
|
|
hadError = true;
|
|
|
|
else {
|
|
|
|
ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.take());
|
|
|
|
if (ExprRes.isInvalid())
|
|
|
|
hadError = true;
|
|
|
|
}
|
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex,
|
|
|
|
ExprRes.takeAs<Expr>());
|
2009-01-31 06:09:00 +08:00
|
|
|
++Index;
|
2011-02-21 15:57:55 +08:00
|
|
|
return;
|
2009-01-31 06:09:00 +08:00
|
|
|
}
|
2011-04-09 02:41:53 +08:00
|
|
|
ExprRes.release();
|
2011-02-21 15:57:55 +08:00
|
|
|
// Fall through for subaggregate initialization
|
|
|
|
}
|
|
|
|
|
|
|
|
// C++ [dcl.init.aggr]p12:
|
|
|
|
//
|
|
|
|
// [...] Otherwise, if the member is itself a non-empty
|
|
|
|
// subaggregate, brace elision is assumed and the initializer is
|
|
|
|
// considered for the initialization of the first member of
|
|
|
|
// the subaggregate.
|
2011-07-16 07:07:01 +08:00
|
|
|
if (!SemaRef.getLangOptions().OpenCL &&
|
|
|
|
(ElemType->isAggregateType() || ElemType->isVectorType())) {
|
2011-02-21 15:57:55 +08:00
|
|
|
CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
|
|
|
|
StructuredIndex);
|
|
|
|
++StructuredIndex;
|
|
|
|
} else {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly) {
|
|
|
|
// We cannot initialize this element, so let
|
|
|
|
// PerformCopyInitialization produce the appropriate diagnostic.
|
|
|
|
SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
|
|
|
|
SemaRef.Owned(expr),
|
|
|
|
/*TopLevelOfInitList=*/true);
|
|
|
|
}
|
2011-02-21 15:57:55 +08:00
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
2009-01-31 06:09:00 +08:00
|
|
|
}
|
2008-05-20 03:16:24 +08:00
|
|
|
}
|
|
|
|
|
2011-09-20 07:17:44 +08:00
|
|
|
void InitListChecker::CheckComplexType(const InitializedEntity &Entity,
|
|
|
|
InitListExpr *IList, QualType DeclType,
|
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
|
|
|
assert(Index == 0 && "Index in explicit init list must be zero");
|
|
|
|
|
|
|
|
// As an extension, clang supports complex initializers, which initialize
|
|
|
|
// a complex number component-wise. When an explicit initializer list for
|
|
|
|
// a complex number contains two two initializers, this extension kicks in:
|
|
|
|
// it exepcts the initializer list to contain two elements convertible to
|
|
|
|
// the element type of the complex type. The first element initializes
|
|
|
|
// the real part, and the second element intitializes the imaginary part.
|
|
|
|
|
|
|
|
if (IList->getNumInits() != 2)
|
|
|
|
return CheckScalarType(Entity, IList, DeclType, Index, StructuredList,
|
|
|
|
StructuredIndex);
|
|
|
|
|
|
|
|
// This is an extension in C. (The builtin _Complex type does not exist
|
|
|
|
// in the C++ standard.)
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!SemaRef.getLangOptions().CPlusPlus && !VerifyOnly)
|
2011-09-20 07:17:44 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init)
|
|
|
|
<< IList->getSourceRange();
|
|
|
|
|
|
|
|
// Initialize the complex number.
|
|
|
|
QualType elementType = DeclType->getAs<ComplexType>()->getElementType();
|
|
|
|
InitializedEntity ElementEntity =
|
|
|
|
InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 2; ++i) {
|
|
|
|
ElementEntity.setElementIndex(Index);
|
|
|
|
CheckSubElementType(ElementEntity, IList, elementType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList, QualType DeclType,
|
2009-01-29 08:39:20 +08:00
|
|
|
unsigned &Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2010-11-11 08:46:36 +08:00
|
|
|
if (Index >= IList->getNumInits()) {
|
2011-09-25 01:48:14 +08:00
|
|
|
if (!SemaRef.getLangOptions().CPlusPlus0x) {
|
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
|
|
|
|
<< IList->getSourceRange();
|
|
|
|
hadError = true;
|
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
2008-05-20 04:12:18 +08:00
|
|
|
return;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2010-11-11 08:46:36 +08:00
|
|
|
|
|
|
|
Expr *expr = IList->getInit(Index);
|
|
|
|
if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(SubIList->getLocStart(),
|
|
|
|
diag::warn_many_braces_around_scalar_init)
|
|
|
|
<< SubIList->getSourceRange();
|
2010-11-11 08:46:36 +08:00
|
|
|
|
|
|
|
CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
|
|
|
|
StructuredIndex);
|
|
|
|
return;
|
|
|
|
} else if (isa<DesignatedInitExpr>(expr)) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(expr->getSourceRange().getBegin(),
|
|
|
|
diag::err_designator_for_scalar_init)
|
|
|
|
<< DeclType << expr->getSourceRange();
|
2010-11-11 08:46:36 +08:00
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
if (VerifyOnly) {
|
|
|
|
if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
|
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-11 08:46:36 +08:00
|
|
|
ExprResult Result =
|
|
|
|
SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
|
2011-07-27 07:20:30 +08:00
|
|
|
SemaRef.Owned(expr),
|
|
|
|
/*TopLevelOfInitList=*/true);
|
2010-11-11 08:46:36 +08:00
|
|
|
|
|
|
|
Expr *ResultExpr = 0;
|
|
|
|
|
|
|
|
if (Result.isInvalid())
|
|
|
|
hadError = true; // types weren't compatible.
|
|
|
|
else {
|
|
|
|
ResultExpr = Result.takeAs<Expr>();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-11-11 08:46:36 +08:00
|
|
|
if (ResultExpr != expr) {
|
|
|
|
// The type was promoted, update initializer list.
|
|
|
|
IList->setInit(Index, ResultExpr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hadError)
|
|
|
|
++StructuredIndex;
|
|
|
|
else
|
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
|
|
|
|
++Index;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
|
|
|
|
InitListExpr *IList, QualType DeclType,
|
2009-01-31 06:09:00 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (Index >= IList->getNumInits()) {
|
2009-05-16 15:39:55 +08:00
|
|
|
// 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.
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(IList->getLocStart(),
|
|
|
|
diag::err_init_reference_member_uninitialized)
|
|
|
|
<< DeclType
|
|
|
|
<< IList->getSourceRange();
|
2009-01-31 06:09:00 +08:00
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
|
|
|
return;
|
|
|
|
}
|
2011-09-25 01:48:00 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VerifyOnly) {
|
|
|
|
if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
|
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Result =
|
|
|
|
SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
|
|
|
|
SemaRef.Owned(expr),
|
|
|
|
/*TopLevelOfInitList=*/true);
|
|
|
|
|
|
|
|
if (Result.isInvalid())
|
|
|
|
hadError = true;
|
|
|
|
|
|
|
|
expr = Result.takeAs<Expr>();
|
|
|
|
IList->setInit(Index, expr);
|
|
|
|
|
|
|
|
if (hadError)
|
|
|
|
++StructuredIndex;
|
|
|
|
else
|
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
|
|
|
|
++Index;
|
2009-01-31 06:09:00 +08:00
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
|
2010-01-24 03:55:29 +08:00
|
|
|
InitListExpr *IList, QualType DeclType,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2010-10-30 08:11:39 +08:00
|
|
|
if (Index >= IList->getNumInits())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const VectorType *VT = DeclType->getAs<VectorType>();
|
|
|
|
unsigned maxElements = VT->getNumElements();
|
|
|
|
unsigned numEltsInit = 0;
|
|
|
|
QualType elementType = VT->getElementType();
|
|
|
|
|
|
|
|
if (!SemaRef.getLangOptions().OpenCL) {
|
|
|
|
// If the initializing element is a vector, try to copy-initialize
|
|
|
|
// instead of breaking it apart (which is doomed to failure anyway).
|
|
|
|
Expr *Init = IList->getInit(Index);
|
|
|
|
if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (VerifyOnly) {
|
|
|
|
if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(Init)))
|
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-10-30 08:11:39 +08:00
|
|
|
ExprResult Result =
|
|
|
|
SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(),
|
2011-07-27 07:20:30 +08:00
|
|
|
SemaRef.Owned(Init),
|
|
|
|
/*TopLevelOfInitList=*/true);
|
2010-10-30 08:11:39 +08:00
|
|
|
|
|
|
|
Expr *ResultExpr = 0;
|
|
|
|
if (Result.isInvalid())
|
|
|
|
hadError = true; // types weren't compatible.
|
|
|
|
else {
|
|
|
|
ResultExpr = Result.takeAs<Expr>();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-10-30 08:11:39 +08:00
|
|
|
if (ResultExpr != Init) {
|
|
|
|
// The type was promoted, update initializer list.
|
|
|
|
IList->setInit(Index, ResultExpr);
|
2009-08-11 07:49:36 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-30 08:11:39 +08:00
|
|
|
if (hadError)
|
|
|
|
++StructuredIndex;
|
|
|
|
else
|
2011-09-25 01:48:00 +08:00
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex,
|
|
|
|
ResultExpr);
|
2010-10-30 08:11:39 +08:00
|
|
|
++Index;
|
|
|
|
return;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-10-30 08:11:39 +08:00
|
|
|
InitializedEntity ElementEntity =
|
|
|
|
InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-10-30 08:11:39 +08:00
|
|
|
for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) {
|
|
|
|
// Don't attempt to go past the end of the init list
|
|
|
|
if (Index >= IList->getNumInits())
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-10-30 08:11:39 +08:00
|
|
|
ElementEntity.setElementIndex(Index);
|
|
|
|
CheckSubElementType(ElementEntity, IList, elementType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
InitializedEntity ElementEntity =
|
|
|
|
InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-10-30 08:11:39 +08:00
|
|
|
// OpenCL initializers allows vectors to be constructed from vectors.
|
|
|
|
for (unsigned i = 0; i < maxElements; ++i) {
|
|
|
|
// Don't attempt to go past the end of the init list
|
|
|
|
if (Index >= IList->getNumInits())
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-10-30 08:11:39 +08:00
|
|
|
ElementEntity.setElementIndex(Index);
|
|
|
|
|
|
|
|
QualType IType = IList->getInit(Index)->getType();
|
|
|
|
if (!IType->isVectorType()) {
|
|
|
|
CheckSubElementType(ElementEntity, IList, elementType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
++numEltsInit;
|
|
|
|
} else {
|
|
|
|
QualType VecType;
|
|
|
|
const VectorType *IVT = IType->getAs<VectorType>();
|
|
|
|
unsigned numIElts = IVT->getNumElements();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-10-30 08:11:39 +08:00
|
|
|
if (IType->isExtVectorType())
|
|
|
|
VecType = SemaRef.Context.getExtVectorType(elementType, numIElts);
|
|
|
|
else
|
|
|
|
VecType = SemaRef.Context.getVectorType(elementType, numIElts,
|
2010-11-11 05:56:12 +08:00
|
|
|
IVT->getVectorKind());
|
2010-10-30 08:11:39 +08:00
|
|
|
CheckSubElementType(ElementEntity, IList, VecType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
numEltsInit += numIElts;
|
|
|
|
}
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2010-10-30 08:11:39 +08:00
|
|
|
|
|
|
|
// OpenCL requires all elements to be initialized.
|
2011-09-25 01:48:00 +08:00
|
|
|
// 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;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
|
2010-01-24 04:13:41 +08:00
|
|
|
InitListExpr *IList, QualType &DeclType,
|
2009-01-23 07:26:18 +08:00
|
|
|
llvm::APSInt elementIndex,
|
2009-09-09 23:08:12 +08:00
|
|
|
bool SubobjectIsDesignatorContext,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2011-02-21 15:22:22 +08:00
|
|
|
const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType);
|
|
|
|
|
2008-05-02 06:18:59 +08:00
|
|
|
// Check for the special-case of initializing an array with a string.
|
|
|
|
if (Index < IList->getNumInits()) {
|
2011-02-21 15:22:22 +08:00
|
|
|
if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType,
|
2009-02-25 07:10:27 +08:00
|
|
|
SemaRef.Context)) {
|
2009-01-29 05:54:33 +08:00
|
|
|
// We place the string literal directly into the resulting
|
|
|
|
// initializer list. This is the only place where the structure
|
|
|
|
// of the structured initializer list doesn't match exactly,
|
|
|
|
// because doing so would involve allocating one character
|
|
|
|
// constant for each string.
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly) {
|
2011-09-27 03:09:09 +08:00
|
|
|
CheckStringInit(Str, DeclType, arrayType, SemaRef);
|
2011-09-25 01:48:00 +08:00
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
|
|
|
|
StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
|
|
|
|
}
|
2008-05-02 06:18:59 +08:00
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2011-02-21 15:22:22 +08:00
|
|
|
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(arrayType)) {
|
2008-05-25 21:22:35 +08:00
|
|
|
// 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).
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
|
|
|
|
diag::err_variable_object_no_init)
|
|
|
|
<< VAT->getSizeExpr()->getSourceRange();
|
2008-05-25 21:22:35 +08:00
|
|
|
hadError = true;
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
2008-05-25 21:22:35 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
// We might know the maximum number of elements in advance.
|
2009-01-29 05:54:33 +08:00
|
|
|
llvm::APSInt maxElements(elementIndex.getBitWidth(),
|
|
|
|
elementIndex.isUnsigned());
|
2009-01-22 08:58:24 +08:00
|
|
|
bool maxElementsKnown = false;
|
2011-02-21 15:22:22 +08:00
|
|
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(arrayType)) {
|
2009-01-22 08:58:24 +08:00
|
|
|
maxElements = CAT->getSize();
|
2010-12-07 16:25:34 +08:00
|
|
|
elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth());
|
2009-01-24 02:58:42 +08:00
|
|
|
elementIndex.setIsUnsigned(maxElements.isUnsigned());
|
2009-01-22 08:58:24 +08:00
|
|
|
maxElementsKnown = true;
|
|
|
|
}
|
|
|
|
|
2011-02-21 15:22:22 +08:00
|
|
|
QualType elementType = arrayType->getElementType();
|
2009-01-22 08:58:24 +08:00
|
|
|
while (Index < IList->getNumInits()) {
|
|
|
|
Expr *Init = IList->getInit(Index);
|
|
|
|
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
|
2009-01-23 07:26:18 +08:00
|
|
|
// If we're not the subobject that matches up with the '{' for
|
|
|
|
// the designator, we shouldn't be handling the
|
|
|
|
// designator. Return immediately.
|
|
|
|
if (!SubobjectIsDesignatorContext)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Handle this designated initializer. elementIndex will be
|
|
|
|
// updated to be the next array element we'll initialize.
|
2010-01-24 06:49:02 +08:00
|
|
|
if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
|
2009-01-29 05:54:33 +08:00
|
|
|
DeclType, 0, &elementIndex, Index,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredList, StructuredIndex, true,
|
|
|
|
false)) {
|
2009-01-22 08:58:24 +08:00
|
|
|
hadError = true;
|
2009-01-23 07:26:18 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-01-24 00:54:12 +08:00
|
|
|
if (elementIndex.getBitWidth() > maxElements.getBitWidth())
|
2010-12-07 16:25:34 +08:00
|
|
|
maxElements = maxElements.extend(elementIndex.getBitWidth());
|
2009-01-24 00:54:12 +08:00
|
|
|
else if (elementIndex.getBitWidth() < maxElements.getBitWidth())
|
2010-12-07 16:25:34 +08:00
|
|
|
elementIndex = elementIndex.extend(maxElements.getBitWidth());
|
2009-01-24 02:58:42 +08:00
|
|
|
elementIndex.setIsUnsigned(maxElements.isUnsigned());
|
2009-01-24 00:54:12 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// If the array is of incomplete type, keep track of the number of
|
|
|
|
// elements in the initializer.
|
|
|
|
if (!maxElementsKnown && elementIndex > maxElements)
|
|
|
|
maxElements = elementIndex;
|
2009-01-22 08:58:24 +08:00
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we know the maximum number of elements, and we've already
|
|
|
|
// hit it, stop consuming elements in the initializer list.
|
|
|
|
if (maxElementsKnown && elementIndex == maxElements)
|
2008-05-02 06:18:59 +08:00
|
|
|
break;
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
InitializedEntity ElementEntity =
|
2011-01-27 15:10:08 +08:00
|
|
|
InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex,
|
2010-01-24 07:23:01 +08:00
|
|
|
Entity);
|
|
|
|
// Check this element.
|
|
|
|
CheckSubElementType(ElementEntity, IList, elementType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
2009-01-22 08:58:24 +08:00
|
|
|
++elementIndex;
|
|
|
|
|
|
|
|
// If the array is of incomplete type, keep track of the number of
|
|
|
|
// elements in the initializer.
|
|
|
|
if (!maxElementsKnown && elementIndex > maxElements)
|
|
|
|
maxElements = elementIndex;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!hadError && DeclType->isIncompleteArrayType() && !VerifyOnly) {
|
2008-05-02 06:18:59 +08:00
|
|
|
// If this is an incomplete array type, the actual type needs to
|
2008-08-19 04:28:46 +08:00
|
|
|
// be calculated here.
|
2009-01-24 02:58:42 +08:00
|
|
|
llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
|
2009-01-22 08:58:24 +08:00
|
|
|
if (maxElements == Zero) {
|
2008-08-19 04:28:46 +08:00
|
|
|
// Sizing an array implicitly to zero is not allowed by ISO C,
|
|
|
|
// but is supported by GNU.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(),
|
2008-08-19 04:28:46 +08:00
|
|
|
diag::ext_typecheck_zero_array_size);
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2008-08-19 04:28:46 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements,
|
2008-08-19 04:28:46 +08:00
|
|
|
ArrayType::Normal, 0);
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-24 06:24:57 +08:00
|
|
|
bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
|
|
|
|
Expr *InitExpr,
|
|
|
|
FieldDecl *Field,
|
|
|
|
bool TopLevelObject) {
|
|
|
|
// Handle GNU flexible array initializers.
|
|
|
|
unsigned FlexArrayDiag;
|
|
|
|
if (isa<InitListExpr>(InitExpr) &&
|
|
|
|
cast<InitListExpr>(InitExpr)->getNumInits() == 0) {
|
|
|
|
// Empty flexible array init always allowed as an extension
|
|
|
|
FlexArrayDiag = diag::ext_flexible_array_init;
|
|
|
|
} else if (SemaRef.getLangOptions().CPlusPlus) {
|
|
|
|
// Disallow flexible array init in C++; it is not required for gcc
|
|
|
|
// compatibility, and it needs work to IRGen correctly in general.
|
|
|
|
FlexArrayDiag = diag::err_flexible_array_init;
|
|
|
|
} else if (!TopLevelObject) {
|
|
|
|
// Disallow flexible array init on non-top-level object
|
|
|
|
FlexArrayDiag = diag::err_flexible_array_init;
|
|
|
|
} else if (Entity.getKind() != InitializedEntity::EK_Variable) {
|
|
|
|
// Disallow flexible array init on anything which is not a variable.
|
|
|
|
FlexArrayDiag = diag::err_flexible_array_init;
|
|
|
|
} else if (cast<VarDecl>(Entity.getDecl())->hasLocalStorage()) {
|
|
|
|
// Disallow flexible array init on local variables.
|
|
|
|
FlexArrayDiag = diag::err_flexible_array_init;
|
|
|
|
} else {
|
|
|
|
// Allow other cases.
|
|
|
|
FlexArrayDiag = diag::ext_flexible_array_init;
|
|
|
|
}
|
2011-09-25 01:48:00 +08:00
|
|
|
|
|
|
|
if (!VerifyOnly) {
|
|
|
|
SemaRef.Diag(InitExpr->getSourceRange().getBegin(),
|
|
|
|
FlexArrayDiag)
|
|
|
|
<< InitExpr->getSourceRange().getBegin();
|
|
|
|
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
|
|
|
|
<< Field;
|
|
|
|
}
|
2011-08-24 06:24:57 +08:00
|
|
|
|
|
|
|
return FlexArrayDiag != diag::ext_flexible_array_init;
|
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
|
2010-01-24 04:20:40 +08:00
|
|
|
InitListExpr *IList,
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType DeclType,
|
2009-01-23 07:26:18 +08:00
|
|
|
RecordDecl::field_iterator Field,
|
2009-09-09 23:08:12 +08:00
|
|
|
bool SubobjectIsDesignatorContext,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject) {
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl* structDecl = DeclType->getAs<RecordType>()->getDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-20 03:16:24 +08:00
|
|
|
// If the record is invalid, some of it's members are invalid. To avoid
|
|
|
|
// confusion, we forgo checking the intializer for the entire record.
|
|
|
|
if (structDecl->isInvalidDecl()) {
|
|
|
|
hadError = true;
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-01-30 01:44:32 +08:00
|
|
|
|
|
|
|
if (DeclType->isUnionType() && IList->getNumInits() == 0) {
|
2011-09-25 01:48:00 +08:00
|
|
|
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();
|
|
|
|
Field != FieldEnd; ++Field) {
|
|
|
|
if (Field->getDeclName()) {
|
|
|
|
StructuredList->setInitializedFieldInUnion(*Field);
|
|
|
|
break;
|
|
|
|
}
|
2009-01-30 01:44:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
// If structDecl is a forward declaration, this loop won't do
|
|
|
|
// anything except look at designated initializers; That's okay,
|
|
|
|
// because an error should get printed out elsewhere. It might be
|
|
|
|
// worthwhile to skip over the rest of the initializer, though.
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
|
2009-06-30 10:36:12 +08:00
|
|
|
RecordDecl::field_iterator FieldEnd = RD->field_end();
|
2009-02-13 03:00:39 +08:00
|
|
|
bool InitializedSomething = false;
|
2010-03-12 03:32:38 +08:00
|
|
|
bool CheckForMissingFields = true;
|
2009-01-22 08:58:24 +08:00
|
|
|
while (Index < IList->getNumInits()) {
|
|
|
|
Expr *Init = IList->getInit(Index);
|
|
|
|
|
|
|
|
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
|
2009-01-23 07:26:18 +08:00
|
|
|
// If we're not the subobject that matches up with the '{' for
|
|
|
|
// the designator, we shouldn't be handling the
|
|
|
|
// designator. Return immediately.
|
|
|
|
if (!SubobjectIsDesignatorContext)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Handle this designated initializer. Field will be updated to
|
|
|
|
// the next field that we'll be initializing.
|
2010-01-24 06:49:02 +08:00
|
|
|
if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
|
2009-01-29 05:54:33 +08:00
|
|
|
DeclType, &Field, 0, Index,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredList, StructuredIndex,
|
|
|
|
true, TopLevelObject))
|
2009-01-22 08:58:24 +08:00
|
|
|
hadError = true;
|
|
|
|
|
2009-02-13 03:00:39 +08:00
|
|
|
InitializedSomething = true;
|
2010-03-12 03:32:38 +08:00
|
|
|
|
|
|
|
// Disable check for missing fields when designators are used.
|
|
|
|
// This matches gcc behaviour.
|
|
|
|
CheckForMissingFields = false;
|
2009-01-22 08:58:24 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Field == FieldEnd) {
|
|
|
|
// We've run out of fields. We're done.
|
2008-12-12 00:49:14 +08:00
|
|
|
break;
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-02-13 03:00:39 +08:00
|
|
|
// We've already initialized a member of a union. We're done.
|
|
|
|
if (InitializedSomething && DeclType->isUnionType())
|
|
|
|
break;
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
// If we've hit the flexible array member at the end, we're done.
|
|
|
|
if (Field->getType()->isIncompleteArrayType())
|
2008-05-20 03:16:24 +08:00
|
|
|
break;
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-01-30 00:53:55 +08:00
|
|
|
if (Field->isUnnamedBitfield()) {
|
2009-01-29 05:54:33 +08:00
|
|
|
// Don't initialize unnamed bitfields, e.g. "int : 20;"
|
2009-01-22 08:58:24 +08:00
|
|
|
++Field;
|
2008-05-20 03:16:24 +08:00
|
|
|
continue;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2011-06-30 05:51:31 +08:00
|
|
|
// Make sure we can use this declaration.
|
2011-09-25 01:48:00 +08:00
|
|
|
bool InvalidUse;
|
|
|
|
if (VerifyOnly)
|
|
|
|
InvalidUse = !SemaRef.CanUseDecl(*Field);
|
|
|
|
else
|
|
|
|
InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field,
|
|
|
|
IList->getInit(Index)->getLocStart());
|
|
|
|
if (InvalidUse) {
|
2011-06-30 05:51:31 +08:00
|
|
|
++Index;
|
|
|
|
++Field;
|
|
|
|
hadError = true;
|
|
|
|
continue;
|
2011-09-25 01:48:00 +08:00
|
|
|
}
|
2011-06-30 05:51:31 +08:00
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
InitializedEntity MemberEntity =
|
|
|
|
InitializedEntity::InitializeMember(*Field, &Entity);
|
|
|
|
CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
|
|
|
|
StructuredList, StructuredIndex);
|
2009-02-13 03:00:39 +08:00
|
|
|
InitializedSomething = true;
|
2009-01-30 00:53:55 +08:00
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
if (DeclType->isUnionType() && !VerifyOnly) {
|
2009-01-30 00:53:55 +08:00
|
|
|
// Initialize the first field within the union.
|
|
|
|
StructuredList->setInitializedFieldInUnion(*Field);
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
|
|
|
++Field;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2010-03-12 03:32:38 +08:00
|
|
|
// Emit warnings for missing struct field initializers.
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
|
|
|
|
Field != FieldEnd && !Field->getType()->isIncompleteArrayType() &&
|
|
|
|
!DeclType->isUnionType()) {
|
2010-03-12 03:32:38 +08:00
|
|
|
// 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();
|
|
|
|
it != end; ++it) {
|
|
|
|
if (!it->isUnnamedBitfield()) {
|
|
|
|
SemaRef.Diag(IList->getSourceRange().getEnd(),
|
|
|
|
diag::warn_missing_field_initializers) << it->getName();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() ||
|
2009-03-20 08:32:56 +08:00
|
|
|
Index >= IList->getNumInits())
|
2009-02-05 06:46:25 +08:00
|
|
|
return;
|
|
|
|
|
2011-08-24 06:24:57 +08:00
|
|
|
if (CheckFlexibleArrayInit(Entity, IList->getInit(Index), *Field,
|
|
|
|
TopLevelObject)) {
|
2009-02-05 06:46:25 +08:00
|
|
|
hadError = true;
|
2009-03-20 08:32:56 +08:00
|
|
|
++Index;
|
|
|
|
return;
|
2009-02-05 06:46:25 +08:00
|
|
|
}
|
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
InitializedEntity MemberEntity =
|
|
|
|
InitializedEntity::InitializeMember(*Field, &Entity);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
if (isa<InitListExpr>(IList->getInit(Index)))
|
2011-01-27 15:10:08 +08:00
|
|
|
CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
|
2010-01-24 07:23:01 +08:00
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
else
|
2011-01-27 15:10:08 +08:00
|
|
|
CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
|
2010-01-24 04:47:59 +08:00
|
|
|
StructuredList, StructuredIndex);
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2009-04-15 14:41:24 +08:00
|
|
|
/// \brief Expand a field designator that refers to a member of an
|
|
|
|
/// anonymous struct or union into a series of field designators that
|
|
|
|
/// refers to the field within the appropriate subobject.
|
|
|
|
///
|
|
|
|
static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
|
2009-09-09 23:08:12 +08:00
|
|
|
DesignatedInitExpr *DIE,
|
|
|
|
unsigned DesigIdx,
|
2010-12-22 11:46:10 +08:00
|
|
|
IndirectFieldDecl *IndirectField) {
|
2009-04-15 14:41:24 +08:00
|
|
|
typedef DesignatedInitExpr::Designator Designator;
|
|
|
|
|
|
|
|
// Build the replacement designators.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Designator, 4> Replacements;
|
2010-12-22 11:46:10 +08:00
|
|
|
for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
|
|
|
|
PE = IndirectField->chain_end(); PI != PE; ++PI) {
|
|
|
|
if (PI + 1 == PE)
|
2009-09-09 23:08:12 +08:00
|
|
|
Replacements.push_back(Designator((IdentifierInfo *)0,
|
2009-04-15 14:41:24 +08:00
|
|
|
DIE->getDesignator(DesigIdx)->getDotLoc(),
|
|
|
|
DIE->getDesignator(DesigIdx)->getFieldLoc()));
|
|
|
|
else
|
|
|
|
Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
|
|
|
|
SourceLocation()));
|
2010-12-22 11:46:10 +08:00
|
|
|
assert(isa<FieldDecl>(*PI));
|
|
|
|
Replacements.back().setField(cast<FieldDecl>(*PI));
|
2009-04-15 14:41:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Expand the current designator into the set of replacement
|
|
|
|
// designators, so we have a full subobject path down to where the
|
|
|
|
// member of the anonymous struct/union is actually stored.
|
2010-01-07 07:17:19 +08:00
|
|
|
DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0],
|
2009-04-15 14:41:24 +08:00
|
|
|
&Replacements[0] + Replacements.size());
|
2010-12-22 11:46:10 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
/// \brief Given an implicit anonymous field, search the IndirectField that
|
2010-12-22 11:46:10 +08:00
|
|
|
/// corresponds to FieldName.
|
|
|
|
static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
|
|
|
|
IdentifierInfo *FieldName) {
|
|
|
|
assert(AnonField->isAnonymousStructOrUnion());
|
|
|
|
Decl *NextDecl = AnonField->getNextDeclInContext();
|
|
|
|
while (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(NextDecl)) {
|
|
|
|
if (FieldName && FieldName == IF->getAnonField()->getIdentifier())
|
|
|
|
return IF;
|
|
|
|
NextDecl = NextDecl->getNextDeclInContext();
|
2009-04-15 14:41:24 +08:00
|
|
|
}
|
2010-12-22 11:46:10 +08:00
|
|
|
return 0;
|
2009-04-15 14:41:24 +08:00
|
|
|
}
|
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
/// @brief Check the well-formedness of a C99 designated initializer.
|
|
|
|
///
|
|
|
|
/// Determines whether the designated initializer @p DIE, which
|
|
|
|
/// resides at the given @p Index within the initializer list @p
|
|
|
|
/// IList, is well-formed for a current object of type @p DeclType
|
|
|
|
/// (C99 6.7.8). The actual subobject that this designator refers to
|
2009-09-09 23:08:12 +08:00
|
|
|
/// within the current subobject is returned in either
|
2009-01-29 05:54:33 +08:00
|
|
|
/// @p NextField or @p NextElementIndex (whichever is appropriate).
|
2009-01-22 08:58:24 +08:00
|
|
|
///
|
|
|
|
/// @param IList The initializer list in which this designated
|
|
|
|
/// initializer occurs.
|
|
|
|
///
|
2009-04-15 12:56:10 +08:00
|
|
|
/// @param DIE The designated initializer expression.
|
|
|
|
///
|
|
|
|
/// @param DesigIdx The index of the current designator.
|
2009-01-22 08:58:24 +08:00
|
|
|
///
|
|
|
|
/// @param DeclType The type of the "current object" (C99 6.7.8p17),
|
|
|
|
/// into which the designation in @p DIE should refer.
|
|
|
|
///
|
2009-01-23 07:26:18 +08:00
|
|
|
/// @param NextField If non-NULL and the first designator in @p DIE is
|
|
|
|
/// a field, this will be set to the field declaration corresponding
|
|
|
|
/// to the field named by the designator.
|
2009-01-22 08:58:24 +08:00
|
|
|
///
|
2009-01-23 07:26:18 +08:00
|
|
|
/// @param NextElementIndex If non-NULL and the first designator in @p
|
|
|
|
/// DIE is an array designator or GNU array-range designator, this
|
|
|
|
/// will be set to the last index initialized by this designator.
|
2009-01-22 08:58:24 +08:00
|
|
|
///
|
|
|
|
/// @param Index Index into @p IList where the designated initializer
|
|
|
|
/// @p DIE occurs.
|
|
|
|
///
|
2009-01-29 05:54:33 +08:00
|
|
|
/// @param StructuredList The initializer list expression that
|
|
|
|
/// describes all of the subobject initializers in the order they'll
|
|
|
|
/// actually be initialized.
|
|
|
|
///
|
2009-01-22 08:58:24 +08:00
|
|
|
/// @returns true if there was an error, false otherwise.
|
2009-09-09 23:08:12 +08:00
|
|
|
bool
|
2010-01-24 07:23:01 +08:00
|
|
|
InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
|
2010-01-24 06:49:02 +08:00
|
|
|
InitListExpr *IList,
|
2011-09-25 01:48:00 +08:00
|
|
|
DesignatedInitExpr *DIE,
|
|
|
|
unsigned DesigIdx,
|
|
|
|
QualType &CurrentObjectType,
|
|
|
|
RecordDecl::field_iterator *NextField,
|
|
|
|
llvm::APSInt *NextElementIndex,
|
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
bool FinishSubobjectInit,
|
|
|
|
bool TopLevelObject) {
|
2009-04-15 12:56:10 +08:00
|
|
|
if (DesigIdx == DIE->size()) {
|
2009-01-23 07:26:18 +08:00
|
|
|
// Check the actual initialization for the designated object type.
|
|
|
|
bool prevHadError = hadError;
|
2009-01-29 08:39:20 +08:00
|
|
|
|
|
|
|
// Temporarily remove the designator expression from the
|
|
|
|
// initializer list that the child calls see, so that we don't try
|
|
|
|
// to re-process the designator.
|
|
|
|
unsigned OldIndex = Index;
|
|
|
|
IList->setInit(OldIndex, DIE->getInit());
|
|
|
|
|
2010-01-24 06:49:02 +08:00
|
|
|
CheckSubElementType(Entity, IList, CurrentObjectType, Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList, StructuredIndex);
|
2009-01-29 08:39:20 +08:00
|
|
|
|
|
|
|
// Restore the designated initializer expression in the syntactic
|
|
|
|
// form of the initializer list.
|
|
|
|
if (IList->getInit(OldIndex) != DIE->getInit())
|
|
|
|
DIE->setInit(IList->getInit(OldIndex));
|
|
|
|
IList->setInit(OldIndex, DIE);
|
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
return hadError && !prevHadError;
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-04-15 12:56:10 +08:00
|
|
|
DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
|
2011-09-25 01:48:00 +08:00
|
|
|
bool IsFirstDesignator = (DesigIdx == 0);
|
|
|
|
if (!VerifyOnly) {
|
|
|
|
assert((IsFirstDesignator || StructuredList) &&
|
|
|
|
"Need a non-designated initializer list to start from");
|
|
|
|
|
|
|
|
// Determine the structural initializer list that corresponds to the
|
|
|
|
// current subobject.
|
|
|
|
StructuredList = IsFirstDesignator? SyntacticToSemantic[IList]
|
|
|
|
: getStructuredSubobjectInit(IList, Index, CurrentObjectType,
|
|
|
|
StructuredList, StructuredIndex,
|
|
|
|
SourceRange(D->getStartLocation(),
|
|
|
|
DIE->getSourceRange().getEnd()));
|
|
|
|
assert(StructuredList && "Expected a structured initializer list");
|
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
if (D->isFieldDesignator()) {
|
|
|
|
// C99 6.7.8p7:
|
|
|
|
//
|
|
|
|
// If a designator has the form
|
|
|
|
//
|
|
|
|
// . identifier
|
|
|
|
//
|
|
|
|
// then the current object (defined below) shall have
|
|
|
|
// structure or union type and the identifier shall be the
|
2009-09-09 23:08:12 +08:00
|
|
|
// name of a member of that type.
|
2009-07-30 05:53:49 +08:00
|
|
|
const RecordType *RT = CurrentObjectType->getAs<RecordType>();
|
2009-01-23 07:26:18 +08:00
|
|
|
if (!RT) {
|
|
|
|
SourceLocation Loc = D->getDotLoc();
|
|
|
|
if (Loc.isInvalid())
|
|
|
|
Loc = D->getFieldLoc();
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
|
|
|
|
<< SemaRef.getLangOptions().CPlusPlus << CurrentObjectType;
|
2009-01-23 07:26:18 +08:00
|
|
|
++Index;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Note: we perform a linear search of the fields here, despite
|
|
|
|
// the fact that we have a faster lookup method, because we always
|
|
|
|
// need to compute the field's index.
|
2009-04-15 14:41:24 +08:00
|
|
|
FieldDecl *KnownField = D->getField();
|
2009-01-23 07:26:18 +08:00
|
|
|
IdentifierInfo *FieldName = D->getFieldName();
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned FieldIndex = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
RecordDecl::field_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
Field = RT->getDecl()->field_begin(),
|
|
|
|
FieldEnd = RT->getDecl()->field_end();
|
2009-01-29 05:54:33 +08:00
|
|
|
for (; Field != FieldEnd; ++Field) {
|
|
|
|
if (Field->isUnnamedBitfield())
|
|
|
|
continue;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-12-22 11:46:10 +08:00
|
|
|
// If we find a field representing an anonymous field, look in the
|
|
|
|
// IndirectFieldDecl that follow for the designated initializer.
|
|
|
|
if (!KnownField && Field->isAnonymousStructOrUnion()) {
|
|
|
|
if (IndirectFieldDecl *IF =
|
|
|
|
FindIndirectFieldDesignator(*Field, FieldName)) {
|
2011-09-25 01:48:00 +08:00
|
|
|
// In verify mode, don't modify the original.
|
|
|
|
if (VerifyOnly)
|
|
|
|
DIE = CloneDesignatedInitExpr(SemaRef, DIE);
|
2010-12-22 11:46:10 +08:00
|
|
|
ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF);
|
|
|
|
D = DIE->getDesignator(DesigIdx);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-10-09 04:44:28 +08:00
|
|
|
if (KnownField && KnownField == *Field)
|
|
|
|
break;
|
|
|
|
if (FieldName && FieldName == Field->getIdentifier())
|
2009-01-29 05:54:33 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
++FieldIndex;
|
2009-01-23 07:26:18 +08:00
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
if (Field == FieldEnd) {
|
2011-09-25 10:41:26 +08:00
|
|
|
if (VerifyOnly) {
|
|
|
|
++Index;
|
2011-09-25 01:48:00 +08:00
|
|
|
return true; // No typo correction when just trying this out.
|
2011-09-25 10:41:26 +08:00
|
|
|
}
|
2011-09-25 01:48:00 +08:00
|
|
|
|
2009-04-15 14:41:24 +08:00
|
|
|
// 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),
|
|
|
|
// may find nothing, or may find a member of an anonymous
|
2009-09-09 23:08:12 +08:00
|
|
|
// struct/union.
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
|
2010-01-01 08:03:05 +08:00
|
|
|
FieldDecl *ReplacementField = 0;
|
2009-01-29 05:54:33 +08:00
|
|
|
if (Lookup.first == Lookup.second) {
|
2010-01-01 08:03:05 +08:00
|
|
|
// Name lookup didn't find anything. Determine whether this
|
|
|
|
// was a typo for another field name.
|
2011-01-27 15:10:08 +08:00
|
|
|
LookupResult R(SemaRef, FieldName, D->getFieldLoc(),
|
2010-01-01 08:03:05 +08:00
|
|
|
Sema::LookupMemberName);
|
2011-06-29 00:20:02 +08:00
|
|
|
TypoCorrection Corrected = SemaRef.CorrectTypo(
|
|
|
|
DeclarationNameInfo(FieldName, D->getFieldLoc()),
|
|
|
|
Sema::LookupMemberName, /*Scope=*/NULL, /*SS=*/NULL,
|
|
|
|
RT->getDecl(), false, Sema::CTC_NoKeywords);
|
|
|
|
if ((ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>()) &&
|
2010-08-31 08:36:30 +08:00
|
|
|
ReplacementField->getDeclContext()->getRedeclContext()
|
2010-01-01 08:03:05 +08:00
|
|
|
->Equals(RT->getDecl())) {
|
2011-06-29 00:20:02 +08:00
|
|
|
std::string CorrectedStr(
|
|
|
|
Corrected.getAsString(SemaRef.getLangOptions()));
|
|
|
|
std::string CorrectedQuotedStr(
|
|
|
|
Corrected.getQuoted(SemaRef.getLangOptions()));
|
2011-01-27 15:10:08 +08:00
|
|
|
SemaRef.Diag(D->getFieldLoc(),
|
2010-01-01 08:03:05 +08:00
|
|
|
diag::err_field_designator_unknown_suggest)
|
2011-06-29 00:20:02 +08:00
|
|
|
<< FieldName << CurrentObjectType << CorrectedQuotedStr
|
|
|
|
<< FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr);
|
2011-01-27 15:10:08 +08:00
|
|
|
SemaRef.Diag(ReplacementField->getLocation(),
|
2011-06-29 00:20:02 +08:00
|
|
|
diag::note_previous_decl) << CorrectedQuotedStr;
|
2011-09-25 10:41:26 +08:00
|
|
|
hadError = true;
|
2010-01-01 08:03:05 +08:00
|
|
|
} else {
|
|
|
|
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
|
|
|
|
<< FieldName << CurrentObjectType;
|
|
|
|
++Index;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-01 08:03:05 +08:00
|
|
|
if (!ReplacementField) {
|
2009-01-29 05:54:33 +08:00
|
|
|
// Name lookup found something, but it wasn't a field.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
|
2009-01-29 05:54:33 +08:00
|
|
|
<< FieldName;
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag((*Lookup.first)->getLocation(),
|
2009-01-29 05:54:33 +08:00
|
|
|
diag::note_field_designator_found);
|
2009-04-17 01:49:48 +08:00
|
|
|
++Index;
|
|
|
|
return true;
|
2009-04-15 14:41:24 +08:00
|
|
|
}
|
2010-01-01 08:03:05 +08:00
|
|
|
|
2010-12-22 11:46:10 +08:00
|
|
|
if (!KnownField) {
|
2010-01-01 08:03:05 +08:00
|
|
|
// The replacement field comes from typo correction; find it
|
|
|
|
// in the list of fields.
|
|
|
|
FieldIndex = 0;
|
|
|
|
Field = RT->getDecl()->field_begin();
|
|
|
|
for (; Field != FieldEnd; ++Field) {
|
|
|
|
if (Field->isUnnamedBitfield())
|
|
|
|
continue;
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
if (ReplacementField == *Field ||
|
2010-01-01 08:03:05 +08:00
|
|
|
Field->getIdentifier() == ReplacementField->getIdentifier())
|
|
|
|
break;
|
|
|
|
|
|
|
|
++FieldIndex;
|
|
|
|
}
|
|
|
|
}
|
2009-01-23 07:26:18 +08:00
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
|
|
|
|
// All of the fields of a union are located at the same place in
|
|
|
|
// the initializer list.
|
2009-01-30 00:53:55 +08:00
|
|
|
if (RT->getDecl()->isUnion()) {
|
2009-01-29 05:54:33 +08:00
|
|
|
FieldIndex = 0;
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
StructuredList->setInitializedFieldInUnion(*Field);
|
2009-01-30 00:53:55 +08:00
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
|
2011-06-30 05:51:31 +08:00
|
|
|
// Make sure we can use this declaration.
|
2011-09-25 01:48:00 +08:00
|
|
|
bool InvalidUse;
|
|
|
|
if (VerifyOnly)
|
|
|
|
InvalidUse = !SemaRef.CanUseDecl(*Field);
|
|
|
|
else
|
|
|
|
InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc());
|
|
|
|
if (InvalidUse) {
|
2011-06-30 05:51:31 +08:00
|
|
|
++Index;
|
|
|
|
return true;
|
2011-09-25 01:48:00 +08:00
|
|
|
}
|
2011-06-30 05:51:31 +08:00
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly) {
|
|
|
|
// Update the designator with the field declaration.
|
|
|
|
D->setField(*Field);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
// Make sure that our non-designated initializer list has space
|
|
|
|
// for a subobject corresponding to this field.
|
|
|
|
if (FieldIndex >= StructuredList->getNumInits())
|
|
|
|
StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);
|
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
|
2009-02-05 06:46:25 +08:00
|
|
|
// This designator names a flexible array member.
|
|
|
|
if (Field->getType()->isIncompleteArrayType()) {
|
|
|
|
bool Invalid = false;
|
2009-04-15 12:56:10 +08:00
|
|
|
if ((DesigIdx + 1) != DIE->size()) {
|
2009-02-05 06:46:25 +08:00
|
|
|
// We can't designate an object within the flexible array
|
|
|
|
// member (because GCC doesn't allow it).
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly) {
|
|
|
|
DesignatedInitExpr::Designator *NextD
|
|
|
|
= DIE->getDesignator(DesigIdx + 1);
|
|
|
|
SemaRef.Diag(NextD->getStartLocation(),
|
|
|
|
diag::err_designator_into_flexible_array_member)
|
|
|
|
<< SourceRange(NextD->getStartLocation(),
|
|
|
|
DIE->getSourceRange().getEnd());
|
|
|
|
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
|
|
|
|
<< *Field;
|
|
|
|
}
|
2009-02-05 06:46:25 +08:00
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
2010-10-11 01:49:49 +08:00
|
|
|
if (!hadError && !isa<InitListExpr>(DIE->getInit()) &&
|
|
|
|
!isa<StringLiteral>(DIE->getInit())) {
|
2009-02-05 06:46:25 +08:00
|
|
|
// The initializer is not an initializer list.
|
2011-09-25 01:48:00 +08:00
|
|
|
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;
|
|
|
|
}
|
2009-02-05 06:46:25 +08:00
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
2011-08-24 06:24:57 +08:00
|
|
|
// Check GNU flexible array initializer.
|
|
|
|
if (!Invalid && CheckFlexibleArrayInit(Entity, DIE->getInit(), *Field,
|
|
|
|
TopLevelObject))
|
2009-02-05 06:46:25 +08:00
|
|
|
Invalid = true;
|
|
|
|
|
|
|
|
if (Invalid) {
|
|
|
|
++Index;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the array.
|
|
|
|
bool prevHadError = hadError;
|
|
|
|
unsigned newStructuredIndex = FieldIndex;
|
|
|
|
unsigned OldIndex = Index;
|
|
|
|
IList->setInit(Index, DIE->getInit());
|
2010-01-24 07:23:01 +08:00
|
|
|
|
|
|
|
InitializedEntity MemberEntity =
|
|
|
|
InitializedEntity::InitializeMember(*Field, &Entity);
|
|
|
|
CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredList, newStructuredIndex);
|
2010-01-24 07:23:01 +08:00
|
|
|
|
2009-02-05 06:46:25 +08:00
|
|
|
IList->setInit(OldIndex, DIE);
|
|
|
|
if (hadError && !prevHadError) {
|
|
|
|
++Field;
|
|
|
|
++FieldIndex;
|
|
|
|
if (NextField)
|
|
|
|
*NextField = Field;
|
|
|
|
StructuredIndex = FieldIndex;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Recurse to check later designated subobjects.
|
|
|
|
QualType FieldType = (*Field)->getType();
|
|
|
|
unsigned newStructuredIndex = FieldIndex;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-24 06:49:02 +08:00
|
|
|
InitializedEntity MemberEntity =
|
2010-01-24 07:23:01 +08:00
|
|
|
InitializedEntity::InitializeMember(*Field, &Entity);
|
2011-01-27 15:10:08 +08:00
|
|
|
if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
|
|
|
|
FieldType, 0, 0, Index,
|
2010-01-24 06:49:02 +08:00
|
|
|
StructuredList, newStructuredIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
true, false))
|
|
|
|
return true;
|
|
|
|
}
|
2009-01-23 07:26:18 +08:00
|
|
|
|
|
|
|
// Find the position of the next field to be initialized in this
|
|
|
|
// subobject.
|
|
|
|
++Field;
|
2009-01-29 05:54:33 +08:00
|
|
|
++FieldIndex;
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// If this the first designator, our caller will continue checking
|
|
|
|
// the rest of this struct/class/union subobject.
|
|
|
|
if (IsFirstDesignator) {
|
|
|
|
if (NextField)
|
|
|
|
*NextField = Field;
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredIndex = FieldIndex;
|
2009-01-23 07:26:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-29 07:36:17 +08:00
|
|
|
if (!FinishSubobjectInit)
|
|
|
|
return false;
|
|
|
|
|
2009-04-15 14:41:24 +08:00
|
|
|
// We've already initialized something in the union; we're done.
|
|
|
|
if (RT->getDecl()->isUnion())
|
|
|
|
return hadError;
|
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// Check the remaining fields within this class/struct/union subobject.
|
|
|
|
bool prevHadError = hadError;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-24 07:23:01 +08:00
|
|
|
CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList, FieldIndex);
|
2009-01-23 07:26:18 +08:00
|
|
|
return hadError && !prevHadError;
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// C99 6.7.8p6:
|
|
|
|
//
|
|
|
|
// If a designator has the form
|
|
|
|
//
|
|
|
|
// [ constant-expression ]
|
|
|
|
//
|
|
|
|
// then the current object (defined below) shall have array
|
|
|
|
// type and the expression shall be an integer constant
|
|
|
|
// expression. If the array is of unknown size, any
|
|
|
|
// nonnegative value is valid.
|
|
|
|
//
|
|
|
|
// Additionally, cope with the GNU extension that permits
|
|
|
|
// designators of the form
|
|
|
|
//
|
|
|
|
// [ constant-expression ... constant-expression ]
|
2009-02-25 06:50:46 +08:00
|
|
|
const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType);
|
2009-01-23 07:26:18 +08:00
|
|
|
if (!AT) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly)
|
|
|
|
SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
|
|
|
|
<< CurrentObjectType;
|
2009-01-23 07:26:18 +08:00
|
|
|
++Index;
|
|
|
|
return true;
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
Expr *IndexExpr = 0;
|
2009-01-29 07:36:17 +08:00
|
|
|
llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
|
|
|
|
if (D->isArrayDesignator()) {
|
2009-01-23 07:26:18 +08:00
|
|
|
IndexExpr = DIE->getArrayIndex(*D);
|
2011-10-11 02:28:20 +08:00
|
|
|
DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context);
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedEndIndex = DesignatedStartIndex;
|
|
|
|
} else {
|
2009-01-23 07:26:18 +08:00
|
|
|
assert(D->isArrayRangeDesignator() && "Need array-range designator");
|
2009-04-26 05:59:05 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
DesignatedStartIndex =
|
2011-10-11 02:28:20 +08:00
|
|
|
DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context);
|
2009-09-09 23:08:12 +08:00
|
|
|
DesignatedEndIndex =
|
2011-10-11 02:28:20 +08:00
|
|
|
DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context);
|
2009-01-23 07:26:18 +08:00
|
|
|
IndexExpr = DIE->getArrayRangeEnd(*D);
|
2009-01-29 07:36:17 +08:00
|
|
|
|
2011-02-20 06:28:58 +08:00
|
|
|
// Codegen can't handle evaluating array range designators that have side
|
|
|
|
// effects, because we replicate the AST value for each initialized element.
|
|
|
|
// As such, set the sawArrayRangeDesignator() bit if we initialize multiple
|
|
|
|
// 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()&&
|
2011-09-25 01:48:00 +08:00
|
|
|
DIE->getInit()->HasSideEffects(SemaRef.Context) && !VerifyOnly)
|
2009-01-30 03:42:23 +08:00
|
|
|
FullyStructuredList->sawArrayRangeDesignator();
|
2009-01-23 07:26:18 +08:00
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
if (isa<ConstantArrayType>(AT)) {
|
|
|
|
llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
|
2010-12-07 16:25:34 +08:00
|
|
|
DesignatedStartIndex
|
|
|
|
= DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
|
2010-12-07 16:25:34 +08:00
|
|
|
DesignatedEndIndex
|
|
|
|
= DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
|
|
|
|
if (DesignatedEndIndex >= MaxElements) {
|
2011-09-27 02:53:43 +08:00
|
|
|
if (!VerifyOnly)
|
2011-09-25 01:48:00 +08:00
|
|
|
SemaRef.Diag(IndexExpr->getSourceRange().getBegin(),
|
|
|
|
diag::err_array_designator_too_large)
|
|
|
|
<< DesignatedEndIndex.toString(10) << MaxElements.toString(10)
|
|
|
|
<< IndexExpr->getSourceRange();
|
2009-01-23 07:26:18 +08:00
|
|
|
++Index;
|
|
|
|
return true;
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
2009-01-29 07:36:17 +08:00
|
|
|
} else {
|
|
|
|
// Make sure the bit-widths and signedness match.
|
|
|
|
if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth())
|
2010-12-07 16:25:34 +08:00
|
|
|
DesignatedEndIndex
|
|
|
|
= DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
|
2009-04-26 05:59:05 +08:00
|
|
|
else if (DesignatedStartIndex.getBitWidth() <
|
|
|
|
DesignatedEndIndex.getBitWidth())
|
2010-12-07 16:25:34 +08:00
|
|
|
DesignatedStartIndex
|
|
|
|
= DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedStartIndex.setIsUnsigned(true);
|
|
|
|
DesignatedEndIndex.setIsUnsigned(true);
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Make sure that our non-designated initializer list has space
|
|
|
|
// for a subobject corresponding to this array element.
|
2011-09-25 01:48:00 +08:00
|
|
|
if (!VerifyOnly &&
|
|
|
|
DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
|
2009-09-09 23:08:12 +08:00
|
|
|
StructuredList->resizeInits(SemaRef.Context,
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedEndIndex.getZExtValue() + 1);
|
|
|
|
|
|
|
|
// Repeatedly perform subobject initializations in the range
|
|
|
|
// [DesignatedStartIndex, DesignatedEndIndex].
|
|
|
|
|
|
|
|
// Move to the next designator
|
|
|
|
unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
|
|
|
|
unsigned OldIndex = Index;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-24 06:49:02 +08:00
|
|
|
InitializedEntity ElementEntity =
|
2010-01-24 07:23:01 +08:00
|
|
|
InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
|
2010-01-24 06:49:02 +08:00
|
|
|
|
2009-01-29 07:36:17 +08:00
|
|
|
while (DesignatedStartIndex <= DesignatedEndIndex) {
|
|
|
|
// Recurse to check later designated subobjects.
|
|
|
|
QualType ElementType = AT->getElementType();
|
|
|
|
Index = OldIndex;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-24 06:49:02 +08:00
|
|
|
ElementEntity.setElementIndex(ElementIndex);
|
2011-01-27 15:10:08 +08:00
|
|
|
if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
|
|
|
|
ElementType, 0, 0, Index,
|
2010-01-24 06:49:02 +08:00
|
|
|
StructuredList, ElementIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
(DesignatedStartIndex == DesignatedEndIndex),
|
|
|
|
false))
|
2009-01-29 07:36:17 +08:00
|
|
|
return true;
|
2009-01-23 07:26:18 +08:00
|
|
|
|
2009-01-29 07:36:17 +08:00
|
|
|
// Move to the next index in the array that we'll be initializing.
|
|
|
|
++DesignatedStartIndex;
|
|
|
|
ElementIndex = DesignatedStartIndex.getZExtValue();
|
|
|
|
}
|
2009-01-23 07:26:18 +08:00
|
|
|
|
|
|
|
// If this the first designator, our caller will continue checking
|
|
|
|
// the rest of this array subobject.
|
|
|
|
if (IsFirstDesignator) {
|
|
|
|
if (NextElementIndex)
|
2009-01-29 07:36:17 +08:00
|
|
|
*NextElementIndex = DesignatedStartIndex;
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredIndex = ElementIndex;
|
2009-01-23 07:26:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 07:36:17 +08:00
|
|
|
if (!FinishSubobjectInit)
|
|
|
|
return false;
|
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// Check the remaining elements within this array subobject.
|
2009-01-22 08:58:24 +08:00
|
|
|
bool prevHadError = hadError;
|
2011-01-27 15:10:08 +08:00
|
|
|
CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex,
|
2010-01-24 04:13:41 +08:00
|
|
|
/*SubobjectIsDesignatorContext=*/false, Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList, ElementIndex);
|
2009-09-09 23:08:12 +08:00
|
|
|
return hadError && !prevHadError;
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Get the structured initializer list for a subobject of type
|
|
|
|
// @p CurrentObjectType.
|
|
|
|
InitListExpr *
|
|
|
|
InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
|
|
|
|
QualType CurrentObjectType,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned StructuredIndex,
|
|
|
|
SourceRange InitRange) {
|
2011-09-25 01:48:00 +08:00
|
|
|
if (VerifyOnly)
|
|
|
|
return 0; // No structured list in verification-only mode.
|
2009-01-29 05:54:33 +08:00
|
|
|
Expr *ExistingInit = 0;
|
|
|
|
if (!StructuredList)
|
|
|
|
ExistingInit = SyntacticToSemantic[IList];
|
|
|
|
else if (StructuredIndex < StructuredList->getNumInits())
|
|
|
|
ExistingInit = StructuredList->getInit(StructuredIndex);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
|
|
|
|
return Result;
|
|
|
|
|
|
|
|
if (ExistingInit) {
|
|
|
|
// We are creating an initializer list that initializes the
|
|
|
|
// subobjects of the current object, but there was already an
|
|
|
|
// initialization that completely initialized the current
|
|
|
|
// subobject, e.g., by a compound literal:
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2009-01-29 05:54:33 +08:00
|
|
|
// struct X { int a, b; };
|
|
|
|
// struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2009-01-29 05:54:33 +08:00
|
|
|
// Here, xs[0].a == 0 and xs[0].b == 3, since the second,
|
|
|
|
// designated initializer re-initializes the whole
|
|
|
|
// subobject [0], overwriting previous initializers.
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(InitRange.getBegin(),
|
2009-03-02 01:12:46 +08:00
|
|
|
diag::warn_subobject_initializer_overrides)
|
2009-01-29 05:54:33 +08:00
|
|
|
<< InitRange;
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(ExistingInit->getSourceRange().getBegin(),
|
2009-01-29 05:54:33 +08:00
|
|
|
diag::note_previous_initializer)
|
2009-01-29 07:43:32 +08:00
|
|
|
<< /*FIXME:has side effects=*/0
|
2009-01-29 05:54:33 +08:00
|
|
|
<< ExistingInit->getSourceRange();
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
InitListExpr *Result
|
2010-04-14 07:39:13 +08:00
|
|
|
= new (SemaRef.Context) InitListExpr(SemaRef.Context,
|
|
|
|
InitRange.getBegin(), 0, 0,
|
2010-02-19 09:50:18 +08:00
|
|
|
InitRange.getEnd());
|
2009-03-02 01:12:46 +08:00
|
|
|
|
2010-07-14 02:40:04 +08:00
|
|
|
Result->setType(CurrentObjectType.getNonLValueExprType(SemaRef.Context));
|
2009-01-29 05:54:33 +08:00
|
|
|
|
2009-03-21 07:58:33 +08:00
|
|
|
// Pre-allocate storage for the structured initializer list.
|
|
|
|
unsigned NumElements = 0;
|
2009-03-22 02:13:52 +08:00
|
|
|
unsigned NumInits = 0;
|
2011-04-29 02:53:55 +08:00
|
|
|
bool GotNumInits = false;
|
|
|
|
if (!StructuredList) {
|
2009-03-22 02:13:52 +08:00
|
|
|
NumInits = IList->getNumInits();
|
2011-04-29 02:53:55 +08:00
|
|
|
GotNumInits = true;
|
|
|
|
} else if (Index < IList->getNumInits()) {
|
|
|
|
if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index))) {
|
2009-03-22 02:13:52 +08:00
|
|
|
NumInits = SubList->getNumInits();
|
2011-04-29 02:53:55 +08:00
|
|
|
GotNumInits = true;
|
|
|
|
}
|
2009-03-22 02:13:52 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const ArrayType *AType
|
2009-03-21 07:58:33 +08:00
|
|
|
= SemaRef.Context.getAsArrayType(CurrentObjectType)) {
|
|
|
|
if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) {
|
|
|
|
NumElements = CAType->getSize().getZExtValue();
|
|
|
|
// Simple heuristic so that we don't allocate a very large
|
|
|
|
// initializer with many empty entries at the end.
|
2011-04-29 02:53:55 +08:00
|
|
|
if (GotNumInits && NumElements > NumInits)
|
2009-03-21 07:58:33 +08:00
|
|
|
NumElements = 0;
|
|
|
|
}
|
2009-09-22 07:43:11 +08:00
|
|
|
} else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>())
|
2009-03-21 07:58:33 +08:00
|
|
|
NumElements = VType->getNumElements();
|
2009-07-30 05:53:49 +08:00
|
|
|
else if (const RecordType *RType = CurrentObjectType->getAs<RecordType>()) {
|
2009-03-21 07:58:33 +08:00
|
|
|
RecordDecl *RDecl = RType->getDecl();
|
|
|
|
if (RDecl->isUnion())
|
|
|
|
NumElements = 1;
|
|
|
|
else
|
2009-09-09 23:08:12 +08:00
|
|
|
NumElements = std::distance(RDecl->field_begin(),
|
2009-06-30 10:36:12 +08:00
|
|
|
RDecl->field_end());
|
2009-03-21 07:58:33 +08:00
|
|
|
}
|
|
|
|
|
2010-04-14 07:39:13 +08:00
|
|
|
Result->reserveInits(SemaRef.Context, NumElements);
|
2009-03-21 07:58:33 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Link this new initializer list into the structured initializer
|
|
|
|
// lists.
|
|
|
|
if (StructuredList)
|
2010-04-14 07:39:13 +08:00
|
|
|
StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result);
|
2009-01-29 05:54:33 +08:00
|
|
|
else {
|
|
|
|
Result->setSyntacticForm(IList);
|
|
|
|
SyntacticToSemantic[IList] = Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Update the initializer at index @p StructuredIndex within the
|
|
|
|
/// structured initializer list to the value @p expr.
|
|
|
|
void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex,
|
|
|
|
Expr *expr) {
|
|
|
|
// No structured initializer list to update
|
|
|
|
if (!StructuredList)
|
|
|
|
return;
|
|
|
|
|
2010-04-14 07:39:13 +08:00
|
|
|
if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context,
|
|
|
|
StructuredIndex, expr)) {
|
2009-01-29 05:54:33 +08:00
|
|
|
// This initializer overwrites a previous initializer. Warn.
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(expr->getSourceRange().getBegin(),
|
2009-01-29 05:54:33 +08:00
|
|
|
diag::warn_initializer_overrides)
|
|
|
|
<< expr->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(PrevInit->getSourceRange().getBegin(),
|
2009-01-29 05:54:33 +08:00
|
|
|
diag::note_previous_initializer)
|
2009-01-29 07:43:32 +08:00
|
|
|
<< /*FIXME:has side effects=*/0
|
2009-01-29 05:54:33 +08:00
|
|
|
<< PrevInit->getSourceRange();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
++StructuredIndex;
|
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
/// Check that the given Index expression is a valid array designator
|
|
|
|
/// value. This is essentailly just a wrapper around
|
2009-04-26 05:59:05 +08:00
|
|
|
/// VerifyIntegerConstantExpression that also checks for negative values
|
2009-01-22 08:58:24 +08:00
|
|
|
/// and produces a reasonable diagnostic if there is a
|
|
|
|
/// failure. Returns true if there was an error, false otherwise. If
|
|
|
|
/// everything went okay, Value will receive the value of the constant
|
|
|
|
/// expression.
|
2009-09-09 23:08:12 +08:00
|
|
|
static bool
|
2009-04-26 05:59:05 +08:00
|
|
|
CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
|
2009-01-22 08:58:24 +08:00
|
|
|
SourceLocation Loc = Index->getSourceRange().getBegin();
|
|
|
|
|
|
|
|
// Make sure this is an integer constant expression.
|
2009-04-26 05:59:05 +08:00
|
|
|
if (S.VerifyIntegerConstantExpression(Index, &Value))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (Value.isSigned() && Value.isNegative())
|
|
|
|
return S.Diag(Loc, diag::err_array_designator_negative)
|
2009-01-22 08:58:24 +08:00
|
|
|
<< Value.toString(10) << Index->getSourceRange();
|
|
|
|
|
2009-01-24 05:04:18 +08:00
|
|
|
Value.setIsUnsigned(true);
|
2009-01-22 08:58:24 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
|
2010-11-20 09:29:55 +08:00
|
|
|
SourceLocation Loc,
|
|
|
|
bool GNUSyntax,
|
|
|
|
ExprResult Init) {
|
2009-01-22 08:58:24 +08:00
|
|
|
typedef DesignatedInitExpr::Designator ASTDesignator;
|
|
|
|
|
|
|
|
bool Invalid = false;
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ASTDesignator, 32> Designators;
|
|
|
|
SmallVector<Expr *, 32> InitExpressions;
|
2009-01-22 08:58:24 +08:00
|
|
|
|
|
|
|
// Build designators and check array designator expressions.
|
|
|
|
for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
|
|
|
|
const Designator &D = Desig.getDesignator(Idx);
|
|
|
|
switch (D.getKind()) {
|
|
|
|
case Designator::FieldDesignator:
|
2009-09-09 23:08:12 +08:00
|
|
|
Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(),
|
2009-01-22 08:58:24 +08:00
|
|
|
D.getFieldLoc()));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Designator::ArrayDesignator: {
|
|
|
|
Expr *Index = static_cast<Expr *>(D.getArrayIndex());
|
|
|
|
llvm::APSInt IndexValue;
|
2009-05-22 07:17:49 +08:00
|
|
|
if (!Index->isTypeDependent() &&
|
|
|
|
!Index->isValueDependent() &&
|
|
|
|
CheckArrayDesignatorExpr(*this, Index, IndexValue))
|
2009-01-22 08:58:24 +08:00
|
|
|
Invalid = true;
|
|
|
|
else {
|
|
|
|
Designators.push_back(ASTDesignator(InitExpressions.size(),
|
2009-09-09 23:08:12 +08:00
|
|
|
D.getLBracketLoc(),
|
2009-01-22 08:58:24 +08:00
|
|
|
D.getRBracketLoc()));
|
|
|
|
InitExpressions.push_back(Index);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Designator::ArrayRangeDesignator: {
|
|
|
|
Expr *StartIndex = static_cast<Expr *>(D.getArrayRangeStart());
|
|
|
|
Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd());
|
|
|
|
llvm::APSInt StartValue;
|
|
|
|
llvm::APSInt EndValue;
|
2009-05-22 07:17:49 +08:00
|
|
|
bool StartDependent = StartIndex->isTypeDependent() ||
|
|
|
|
StartIndex->isValueDependent();
|
|
|
|
bool EndDependent = EndIndex->isTypeDependent() ||
|
|
|
|
EndIndex->isValueDependent();
|
|
|
|
if ((!StartDependent &&
|
|
|
|
CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) ||
|
|
|
|
(!EndDependent &&
|
|
|
|
CheckArrayDesignatorExpr(*this, EndIndex, EndValue)))
|
2009-01-22 08:58:24 +08:00
|
|
|
Invalid = true;
|
2009-01-24 06:22:29 +08:00
|
|
|
else {
|
|
|
|
// Make sure we're comparing values with the same bit width.
|
2009-05-22 07:17:49 +08:00
|
|
|
if (StartDependent || EndDependent) {
|
|
|
|
// Nothing to compute.
|
|
|
|
} else if (StartValue.getBitWidth() > EndValue.getBitWidth())
|
2010-12-07 16:25:34 +08:00
|
|
|
EndValue = EndValue.extend(StartValue.getBitWidth());
|
2009-01-24 06:22:29 +08:00
|
|
|
else if (StartValue.getBitWidth() < EndValue.getBitWidth())
|
2010-12-07 16:25:34 +08:00
|
|
|
StartValue = StartValue.extend(EndValue.getBitWidth());
|
2009-01-24 06:22:29 +08:00
|
|
|
|
2009-05-22 07:30:39 +08:00
|
|
|
if (!StartDependent && !EndDependent && EndValue < StartValue) {
|
2009-01-24 06:22:29 +08:00
|
|
|
Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range)
|
2009-09-09 23:08:12 +08:00
|
|
|
<< StartValue.toString(10) << EndValue.toString(10)
|
2009-01-24 06:22:29 +08:00
|
|
|
<< StartIndex->getSourceRange() << EndIndex->getSourceRange();
|
|
|
|
Invalid = true;
|
|
|
|
} else {
|
|
|
|
Designators.push_back(ASTDesignator(InitExpressions.size(),
|
2009-09-09 23:08:12 +08:00
|
|
|
D.getLBracketLoc(),
|
2009-01-24 06:22:29 +08:00
|
|
|
D.getEllipsisLoc(),
|
|
|
|
D.getRBracketLoc()));
|
|
|
|
InitExpressions.push_back(StartIndex);
|
|
|
|
InitExpressions.push_back(EndIndex);
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Invalid || Init.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
// Clear out the expressions within the designation.
|
|
|
|
Desig.ClearExprs(*this);
|
|
|
|
|
|
|
|
DesignatedInitExpr *DIE
|
2009-05-21 17:52:38 +08:00
|
|
|
= DesignatedInitExpr::Create(Context,
|
|
|
|
Designators.data(), Designators.size(),
|
|
|
|
InitExpressions.data(), InitExpressions.size(),
|
2009-05-02 03:49:17 +08:00
|
|
|
Loc, GNUSyntax, Init.takeAs<Expr>());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-01-17 00:13:16 +08:00
|
|
|
if (getLangOptions().CPlusPlus)
|
2011-04-25 06:14:22 +08:00
|
|
|
Diag(DIE->getLocStart(), diag::ext_designated_init_cxx)
|
|
|
|
<< DIE->getSourceRange();
|
|
|
|
else if (!getLangOptions().C99)
|
2011-01-17 00:13:16 +08:00
|
|
|
Diag(DIE->getLocStart(), diag::ext_designated_init)
|
|
|
|
<< DIE->getSourceRange();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
return Owned(DIE);
|
|
|
|
}
|
2009-01-29 08:45:39 +08:00
|
|
|
|
2009-12-16 14:35:08 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Initialization entity
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-09-10 07:08:42 +08:00
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
|
2009-12-16 14:35:08 +08:00
|
|
|
const InitializedEntity &Parent)
|
2011-01-27 15:10:08 +08:00
|
|
|
: Parent(&Parent), Index(Index)
|
2009-12-16 14:35:08 +08:00
|
|
|
{
|
2010-01-23 12:34:47 +08:00
|
|
|
if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) {
|
|
|
|
Kind = EK_ArrayElement;
|
2009-12-22 23:35:07 +08:00
|
|
|
Type = AT->getElementType();
|
2011-09-20 07:17:44 +08:00
|
|
|
} else if (const VectorType *VT = Parent.getType()->getAs<VectorType>()) {
|
2010-01-23 12:34:47 +08:00
|
|
|
Kind = EK_VectorElement;
|
2011-09-20 07:17:44 +08:00
|
|
|
Type = VT->getElementType();
|
|
|
|
} else {
|
|
|
|
const ComplexType *CT = Parent.getType()->getAs<ComplexType>();
|
|
|
|
assert(CT && "Unexpected type");
|
|
|
|
Kind = EK_ComplexElement;
|
|
|
|
Type = CT->getElementType();
|
2010-01-23 12:34:47 +08:00
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
|
2010-04-22 03:52:01 +08:00
|
|
|
CXXBaseSpecifier *Base,
|
|
|
|
bool IsInheritedVirtualBase)
|
2009-12-10 07:02:17 +08:00
|
|
|
{
|
|
|
|
InitializedEntity Result;
|
|
|
|
Result.Kind = EK_Base;
|
2010-04-22 03:52:01 +08:00
|
|
|
Result.Base = reinterpret_cast<uintptr_t>(Base);
|
|
|
|
if (IsInheritedVirtualBase)
|
|
|
|
Result.Base |= 0x01;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-22 23:35:07 +08:00
|
|
|
Result.Type = Base->getType();
|
2009-12-10 07:02:17 +08:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
DeclarationName InitializedEntity::getName() const {
|
|
|
|
switch (getKind()) {
|
2011-06-16 07:02:42 +08:00
|
|
|
case EK_Parameter: {
|
|
|
|
ParmVarDecl *D = reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
|
|
|
|
return (D ? D->getDeclName() : DeclarationName());
|
|
|
|
}
|
2009-12-23 00:09:06 +08:00
|
|
|
|
|
|
|
case EK_Variable:
|
2009-12-16 09:38:02 +08:00
|
|
|
case EK_Member:
|
|
|
|
return VariableOrMember->getDeclName();
|
|
|
|
|
|
|
|
case EK_Result:
|
|
|
|
case EK_Exception:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case EK_New:
|
2009-12-16 09:38:02 +08:00
|
|
|
case EK_Temporary:
|
|
|
|
case EK_Base:
|
2011-05-01 15:04:31 +08:00
|
|
|
case EK_Delegating:
|
2010-01-23 12:34:47 +08:00
|
|
|
case EK_ArrayElement:
|
|
|
|
case EK_VectorElement:
|
2011-09-20 07:17:44 +08:00
|
|
|
case EK_ComplexElement:
|
2010-06-08 00:14:00 +08:00
|
|
|
case EK_BlockElement:
|
2009-12-16 09:38:02 +08:00
|
|
|
return DeclarationName();
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
// Silence GCC warning
|
|
|
|
return DeclarationName();
|
|
|
|
}
|
|
|
|
|
2009-12-19 11:01:41 +08:00
|
|
|
DeclaratorDecl *InitializedEntity::getDecl() const {
|
|
|
|
switch (getKind()) {
|
|
|
|
case EK_Variable:
|
|
|
|
case EK_Member:
|
|
|
|
return VariableOrMember;
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
case EK_Parameter:
|
|
|
|
return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
|
|
|
|
|
2009-12-19 11:01:41 +08:00
|
|
|
case EK_Result:
|
|
|
|
case EK_Exception:
|
|
|
|
case EK_New:
|
|
|
|
case EK_Temporary:
|
|
|
|
case EK_Base:
|
2011-05-01 15:04:31 +08:00
|
|
|
case EK_Delegating:
|
2010-01-23 12:34:47 +08:00
|
|
|
case EK_ArrayElement:
|
|
|
|
case EK_VectorElement:
|
2011-09-20 07:17:44 +08:00
|
|
|
case EK_ComplexElement:
|
2010-06-08 00:14:00 +08:00
|
|
|
case EK_BlockElement:
|
2009-12-19 11:01:41 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-19 11:01:41 +08:00
|
|
|
// Silence GCC warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-05-15 08:13:29 +08:00
|
|
|
bool InitializedEntity::allowsNRVO() const {
|
|
|
|
switch (getKind()) {
|
|
|
|
case EK_Result:
|
|
|
|
case EK_Exception:
|
|
|
|
return LocAndNRVO.NRVO;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-05-15 08:13:29 +08:00
|
|
|
case EK_Variable:
|
|
|
|
case EK_Parameter:
|
|
|
|
case EK_Member:
|
|
|
|
case EK_New:
|
|
|
|
case EK_Temporary:
|
|
|
|
case EK_Base:
|
2011-05-01 15:04:31 +08:00
|
|
|
case EK_Delegating:
|
2010-05-15 08:13:29 +08:00
|
|
|
case EK_ArrayElement:
|
|
|
|
case EK_VectorElement:
|
2011-09-20 07:17:44 +08:00
|
|
|
case EK_ComplexElement:
|
2010-06-08 00:14:00 +08:00
|
|
|
case EK_BlockElement:
|
2010-05-15 08:13:29 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Initialization sequence
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void InitializationSequence::Step::Destroy() {
|
|
|
|
switch (Kind) {
|
|
|
|
case SK_ResolveAddressOfOverloadedFunction:
|
|
|
|
case SK_CastDerivedToBaseRValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
case SK_CastDerivedToBaseXValue:
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_CastDerivedToBaseLValue:
|
|
|
|
case SK_BindReference:
|
|
|
|
case SK_BindReferenceToTemporary:
|
2010-04-18 15:40:54 +08:00
|
|
|
case SK_ExtraneousCopyToTemporary:
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_UserConversion:
|
|
|
|
case SK_QualificationConversionRValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
case SK_QualificationConversionXValue:
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_QualificationConversionLValue:
|
2009-12-11 01:56:55 +08:00
|
|
|
case SK_ListInitialization:
|
2011-09-25 01:47:52 +08:00
|
|
|
case SK_ListConstructorCall:
|
2009-12-15 04:49:26 +08:00
|
|
|
case SK_ConstructorInitialization:
|
2009-12-15 08:01:57 +08:00
|
|
|
case SK_ZeroInitialization:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case SK_CAssignment:
|
2009-12-19 16:11:05 +08:00
|
|
|
case SK_StringInit:
|
2010-08-07 19:51:51 +08:00
|
|
|
case SK_ObjCObjectConversion:
|
2011-02-23 02:29:51 +08:00
|
|
|
case SK_ArrayInit:
|
2011-06-16 07:02:42 +08:00
|
|
|
case SK_PassByIndirectCopyRestore:
|
|
|
|
case SK_PassByIndirectRestore:
|
|
|
|
case SK_ProduceObjCObject:
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_ConversionSequence:
|
|
|
|
delete ICS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:14:36 +08:00
|
|
|
bool InitializationSequence::isDirectReferenceBinding() const {
|
2011-07-15 03:07:55 +08:00
|
|
|
return !Steps.empty() && Steps.back().Kind == SK_BindReference;
|
2010-03-27 04:14:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool InitializationSequence::isAmbiguous() const {
|
2011-06-05 21:59:05 +08:00
|
|
|
if (!Failed())
|
2010-03-27 04:14:36 +08:00
|
|
|
return false;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-03-27 04:14:36 +08:00
|
|
|
switch (getFailureKind()) {
|
|
|
|
case FK_TooManyInitsForReference:
|
|
|
|
case FK_ArrayNeedsInitList:
|
|
|
|
case FK_ArrayNeedsInitListOrStringLiteral:
|
|
|
|
case FK_AddressOfOverloadFailed: // FIXME: Could do better
|
|
|
|
case FK_NonConstLValueReferenceBindingToTemporary:
|
|
|
|
case FK_NonConstLValueReferenceBindingToUnrelated:
|
|
|
|
case FK_RValueReferenceBindingToLValue:
|
|
|
|
case FK_ReferenceInitDropsQualifiers:
|
|
|
|
case FK_ReferenceInitFailed:
|
|
|
|
case FK_ConversionFailed:
|
2011-04-09 02:41:53 +08:00
|
|
|
case FK_ConversionFromPropertyFailed:
|
2010-03-27 04:14:36 +08:00
|
|
|
case FK_TooManyInitsForScalar:
|
|
|
|
case FK_ReferenceBindingToInitList:
|
|
|
|
case FK_InitListBadDestinationType:
|
|
|
|
case FK_DefaultInitOfConst:
|
2010-05-21 06:12:02 +08:00
|
|
|
case FK_Incomplete:
|
2011-02-23 02:29:51 +08:00
|
|
|
case FK_ArrayTypeMismatch:
|
|
|
|
case FK_NonConstantArrayInit:
|
2011-09-25 01:47:52 +08:00
|
|
|
case FK_ListInitializationFailed:
|
2010-03-27 04:14:36 +08:00
|
|
|
return false;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-03-27 04:14:36 +08:00
|
|
|
case FK_ReferenceInitOverloadFailed:
|
|
|
|
case FK_UserConversionOverloadFailed:
|
|
|
|
case FK_ConstructorOverloadFailed:
|
|
|
|
return FailedOverloadResult == OR_Ambiguous;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-03-27 04:14:36 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-04-17 06:09:46 +08:00
|
|
|
bool InitializationSequence::isConstructorInitialization() const {
|
|
|
|
return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization;
|
|
|
|
}
|
|
|
|
|
2011-07-27 07:20:30 +08:00
|
|
|
bool InitializationSequence::endsWithNarrowing(ASTContext &Ctx,
|
|
|
|
const Expr *Initializer,
|
|
|
|
bool *isInitializerConstant,
|
|
|
|
APValue *ConstantValue) const {
|
|
|
|
if (Steps.empty() || Initializer->isValueDependent())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const Step &LastStep = Steps.back();
|
|
|
|
if (LastStep.Kind != SK_ConversionSequence)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const ImplicitConversionSequence &ICS = *LastStep.ICS;
|
|
|
|
const StandardConversionSequence *SCS = NULL;
|
|
|
|
switch (ICS.getKind()) {
|
|
|
|
case ImplicitConversionSequence::StandardConversion:
|
|
|
|
SCS = &ICS.Standard;
|
|
|
|
break;
|
|
|
|
case ImplicitConversionSequence::UserDefinedConversion:
|
|
|
|
SCS = &ICS.UserDefined.After;
|
|
|
|
break;
|
|
|
|
case ImplicitConversionSequence::AmbiguousConversion:
|
|
|
|
case ImplicitConversionSequence::EllipsisConversion:
|
|
|
|
case ImplicitConversionSequence::BadConversion:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if SCS represents a narrowing conversion, according to C++0x
|
|
|
|
// [dcl.init.list]p7:
|
|
|
|
//
|
|
|
|
// A narrowing conversion is an implicit conversion ...
|
|
|
|
ImplicitConversionKind PossibleNarrowing = SCS->Second;
|
|
|
|
QualType FromType = SCS->getToType(0);
|
|
|
|
QualType ToType = SCS->getToType(1);
|
|
|
|
switch (PossibleNarrowing) {
|
|
|
|
// * from a floating-point type to an integer type, or
|
|
|
|
//
|
|
|
|
// * from an integer type or unscoped enumeration type to a floating-point
|
|
|
|
// type, except where the source is a constant expression and the actual
|
|
|
|
// value after conversion will fit into the target type and will produce
|
|
|
|
// the original value when converted back to the original type, or
|
|
|
|
case ICK_Floating_Integral:
|
|
|
|
if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
|
|
|
|
*isInitializerConstant = false;
|
|
|
|
return true;
|
|
|
|
} else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
|
|
|
|
llvm::APSInt IntConstantValue;
|
|
|
|
if (Initializer &&
|
|
|
|
Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
|
|
|
|
// Convert the integer to the floating type.
|
|
|
|
llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
|
|
|
|
Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(),
|
|
|
|
llvm::APFloat::rmNearestTiesToEven);
|
|
|
|
// And back.
|
|
|
|
llvm::APSInt ConvertedValue = IntConstantValue;
|
|
|
|
bool ignored;
|
|
|
|
Result.convertToInteger(ConvertedValue,
|
|
|
|
llvm::APFloat::rmTowardZero, &ignored);
|
|
|
|
// If the resulting value is different, this was a narrowing conversion.
|
|
|
|
if (IntConstantValue != ConvertedValue) {
|
|
|
|
*isInitializerConstant = true;
|
|
|
|
*ConstantValue = APValue(IntConstantValue);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Variables are always narrowings.
|
|
|
|
*isInitializerConstant = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// * from long double to double or float, or from double to float, except
|
|
|
|
// where the source is a constant expression and the actual value after
|
|
|
|
// conversion is within the range of values that can be represented (even
|
|
|
|
// if it cannot be represented exactly), or
|
|
|
|
case ICK_Floating_Conversion:
|
|
|
|
if (1 == Ctx.getFloatingTypeOrder(FromType, ToType)) {
|
|
|
|
// FromType is larger than ToType.
|
|
|
|
Expr::EvalResult InitializerValue;
|
|
|
|
// FIXME: Check whether Initializer is a constant expression according
|
|
|
|
// to C++0x [expr.const], rather than just whether it can be folded.
|
|
|
|
if (Initializer->Evaluate(InitializerValue, Ctx) &&
|
|
|
|
!InitializerValue.HasSideEffects && InitializerValue.Val.isFloat()) {
|
|
|
|
// Constant! (Except for FIXME above.)
|
|
|
|
llvm::APFloat FloatVal = InitializerValue.Val.getFloat();
|
|
|
|
// Convert the source value into the target type.
|
|
|
|
bool ignored;
|
|
|
|
llvm::APFloat::opStatus ConvertStatus = FloatVal.convert(
|
|
|
|
Ctx.getFloatTypeSemantics(ToType),
|
|
|
|
llvm::APFloat::rmNearestTiesToEven, &ignored);
|
|
|
|
// If there was no overflow, the source value is within the range of
|
|
|
|
// values that can be represented.
|
|
|
|
if (ConvertStatus & llvm::APFloat::opOverflow) {
|
|
|
|
*isInitializerConstant = true;
|
|
|
|
*ConstantValue = InitializerValue.Val;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*isInitializerConstant = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// * from an integer type or unscoped enumeration type to an integer type
|
|
|
|
// that cannot represent all the values of the original type, except where
|
|
|
|
// the source is a constant expression and the actual value after
|
|
|
|
// conversion will fit into the target type and will produce the original
|
|
|
|
// value when converted back to the original type.
|
2011-08-13 04:56:43 +08:00
|
|
|
case ICK_Boolean_Conversion: // Bools are integers too.
|
2011-08-31 06:25:41 +08:00
|
|
|
if (!FromType->isIntegralOrUnscopedEnumerationType()) {
|
|
|
|
// Boolean conversions can be from pointers and pointers to members
|
|
|
|
// [conv.bool], and those aren't considered narrowing conversions.
|
|
|
|
return false;
|
|
|
|
} // Otherwise, fall through to the integral case.
|
2011-07-27 07:20:30 +08:00
|
|
|
case ICK_Integral_Conversion: {
|
|
|
|
assert(FromType->isIntegralOrUnscopedEnumerationType());
|
|
|
|
assert(ToType->isIntegralOrUnscopedEnumerationType());
|
|
|
|
const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
|
|
|
|
const unsigned FromWidth = Ctx.getIntWidth(FromType);
|
|
|
|
const bool ToSigned = ToType->isSignedIntegerOrEnumerationType();
|
|
|
|
const unsigned ToWidth = Ctx.getIntWidth(ToType);
|
|
|
|
|
|
|
|
if (FromWidth > ToWidth ||
|
|
|
|
(FromWidth == ToWidth && FromSigned != ToSigned)) {
|
|
|
|
// Not all values of FromType can be represented in ToType.
|
|
|
|
llvm::APSInt InitializerValue;
|
|
|
|
if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) {
|
|
|
|
*isInitializerConstant = true;
|
|
|
|
*ConstantValue = APValue(InitializerValue);
|
|
|
|
|
|
|
|
// Add a bit to the InitializerValue so we don't have to worry about
|
|
|
|
// signed vs. unsigned comparisons.
|
|
|
|
InitializerValue = InitializerValue.extend(
|
|
|
|
InitializerValue.getBitWidth() + 1);
|
|
|
|
// Convert the initializer to and from the target width and signed-ness.
|
|
|
|
llvm::APSInt ConvertedValue = InitializerValue;
|
|
|
|
ConvertedValue = ConvertedValue.trunc(ToWidth);
|
|
|
|
ConvertedValue.setIsSigned(ToSigned);
|
|
|
|
ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth());
|
|
|
|
ConvertedValue.setIsSigned(InitializerValue.isSigned());
|
|
|
|
// If the result is different, this was a narrowing conversion.
|
|
|
|
return ConvertedValue != InitializerValue;
|
|
|
|
} else {
|
|
|
|
// Variables are always narrowings.
|
|
|
|
*isInitializerConstant = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Other kinds of conversions are not narrowings.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
void InitializationSequence::AddAddressOverloadResolutionStep(
|
2010-03-31 05:47:33 +08:00
|
|
|
FunctionDecl *Function,
|
|
|
|
DeclAccessPair Found) {
|
2009-12-10 07:02:17 +08:00
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ResolveAddressOfOverloadedFunction;
|
|
|
|
S.Type = Function->getType();
|
2011-10-10 01:58:25 +08:00
|
|
|
S.Function.HadMultipleCandidates = false;
|
2010-03-19 15:35:19 +08:00
|
|
|
S.Function.Function = Function;
|
2010-03-31 05:47:33 +08:00
|
|
|
S.Function.FoundDecl = Found;
|
2009-12-10 07:02:17 +08:00
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
|
2010-08-25 18:28:54 +08:00
|
|
|
ExprValueKind VK) {
|
2009-12-10 07:02:17 +08:00
|
|
|
Step S;
|
2010-08-25 18:28:54 +08:00
|
|
|
switch (VK) {
|
|
|
|
case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break;
|
|
|
|
case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break;
|
|
|
|
case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break;
|
2010-07-20 12:20:21 +08:00
|
|
|
default: llvm_unreachable("No such category");
|
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
S.Type = BaseType;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
void InitializationSequence::AddReferenceBindingStep(QualType T,
|
2009-12-10 07:02:17 +08:00
|
|
|
bool BindingTemporary) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2010-04-18 15:40:54 +08:00
|
|
|
void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ExtraneousCopyToTemporary;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2009-12-11 10:42:07 +08:00
|
|
|
void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
|
2010-03-19 15:35:19 +08:00
|
|
|
DeclAccessPair FoundDecl,
|
2009-12-11 10:42:07 +08:00
|
|
|
QualType T) {
|
2009-12-10 07:02:17 +08:00
|
|
|
Step S;
|
|
|
|
S.Kind = SK_UserConversion;
|
2009-12-11 10:42:07 +08:00
|
|
|
S.Type = T;
|
2011-10-10 01:58:25 +08:00
|
|
|
S.Function.HadMultipleCandidates = false;
|
2010-03-19 15:35:19 +08:00
|
|
|
S.Function.Function = Function;
|
|
|
|
S.Function.FoundDecl = FoundDecl;
|
2009-12-10 07:02:17 +08:00
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitializationSequence::AddQualificationConversionStep(QualType Ty,
|
2010-08-25 18:28:54 +08:00
|
|
|
ExprValueKind VK) {
|
2009-12-10 07:02:17 +08:00
|
|
|
Step S;
|
2010-08-27 00:36:35 +08:00
|
|
|
S.Kind = SK_QualificationConversionRValue; // work around a gcc warning
|
2010-08-25 18:28:54 +08:00
|
|
|
switch (VK) {
|
|
|
|
case VK_RValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
S.Kind = SK_QualificationConversionRValue;
|
|
|
|
break;
|
2010-08-25 18:28:54 +08:00
|
|
|
case VK_XValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
S.Kind = SK_QualificationConversionXValue;
|
|
|
|
break;
|
2010-08-25 18:28:54 +08:00
|
|
|
case VK_LValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
S.Kind = SK_QualificationConversionLValue;
|
|
|
|
break;
|
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
S.Type = Ty;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitializationSequence::AddConversionSequenceStep(
|
|
|
|
const ImplicitConversionSequence &ICS,
|
|
|
|
QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ConversionSequence;
|
|
|
|
S.Type = T;
|
|
|
|
S.ICS = new ImplicitConversionSequence(ICS);
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2009-12-11 01:56:55 +08:00
|
|
|
void InitializationSequence::AddListInitializationStep(QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ListInitialization;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
void
|
2009-12-15 04:49:26 +08:00
|
|
|
InitializationSequence::AddConstructorInitializationStep(
|
|
|
|
CXXConstructorDecl *Constructor,
|
2010-02-01 11:16:54 +08:00
|
|
|
AccessSpecifier Access,
|
2009-12-15 04:49:26 +08:00
|
|
|
QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ConstructorInitialization;
|
|
|
|
S.Type = T;
|
2011-10-10 01:58:25 +08:00
|
|
|
S.Function.HadMultipleCandidates = false;
|
2010-03-19 15:35:19 +08:00
|
|
|
S.Function.Function = Constructor;
|
|
|
|
S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access);
|
2009-12-15 04:49:26 +08:00
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2009-12-15 08:01:57 +08:00
|
|
|
void InitializationSequence::AddZeroInitializationStep(QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ZeroInitialization;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
void InitializationSequence::AddCAssignmentStep(QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_CAssignment;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2009-12-19 16:11:05 +08:00
|
|
|
void InitializationSequence::AddStringInitStep(QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_StringInit;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2010-08-07 19:51:51 +08:00
|
|
|
void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ObjCObjectConversion;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2011-02-23 02:29:51 +08:00
|
|
|
void InitializationSequence::AddArrayInitStep(QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ArrayInit;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
void InitializationSequence::AddPassByIndirectCopyRestoreStep(QualType type,
|
|
|
|
bool shouldCopy) {
|
|
|
|
Step s;
|
|
|
|
s.Kind = (shouldCopy ? SK_PassByIndirectCopyRestore
|
|
|
|
: SK_PassByIndirectRestore);
|
|
|
|
s.Type = type;
|
|
|
|
Steps.push_back(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitializationSequence::AddProduceObjCObjectStep(QualType T) {
|
|
|
|
Step S;
|
|
|
|
S.Kind = SK_ProduceObjCObject;
|
|
|
|
S.Type = T;
|
|
|
|
Steps.push_back(S);
|
|
|
|
}
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
|
2009-12-10 07:02:17 +08:00
|
|
|
OverloadingResult Result) {
|
2011-06-05 21:59:11 +08:00
|
|
|
setSequenceKind(FailedSequence);
|
2009-12-10 07:02:17 +08:00
|
|
|
this->Failure = Failure;
|
|
|
|
this->FailedOverloadResult = Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Attempt initialization
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
static void MaybeProduceObjCObject(Sema &S,
|
|
|
|
InitializationSequence &Sequence,
|
|
|
|
const InitializedEntity &Entity) {
|
|
|
|
if (!S.getLangOptions().ObjCAutoRefCount) return;
|
|
|
|
|
|
|
|
/// When initializing a parameter, produce the value if it's marked
|
|
|
|
/// __attribute__((ns_consumed)).
|
|
|
|
if (Entity.getKind() == InitializedEntity::EK_Parameter) {
|
|
|
|
if (!Entity.isParameterConsumed())
|
|
|
|
return;
|
|
|
|
|
|
|
|
assert(Entity.getType()->isObjCRetainableType() &&
|
|
|
|
"consuming an object of unretainable type?");
|
|
|
|
Sequence.AddProduceObjCObjectStep(Entity.getType());
|
|
|
|
|
|
|
|
/// When initializing a return value, if the return type is a
|
|
|
|
/// retainable type, then returns need to immediately retain the
|
|
|
|
/// object. If an autorelease is required, it will be done at the
|
|
|
|
/// last instant.
|
|
|
|
} else if (Entity.getKind() == InitializedEntity::EK_Result) {
|
|
|
|
if (!Entity.getType()->isObjCRetainableType())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Sequence.AddProduceObjCObjectStep(Entity.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-15 06:58:04 +08:00
|
|
|
/// \brief Attempt list initialization (C++0x [dcl.init.list])
|
|
|
|
static void TryListInitialization(Sema &S,
|
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
InitListExpr *InitList,
|
|
|
|
InitializationSequence &Sequence) {
|
|
|
|
QualType DestType = Entity.getType();
|
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
// FIXME: C++0x defines behavior for these two cases.
|
|
|
|
if (DestType->isReferenceType()) {
|
2011-07-15 06:58:04 +08:00
|
|
|
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
|
|
|
|
return;
|
2011-09-25 01:48:00 +08:00
|
|
|
}
|
|
|
|
if (DestType->isRecordType() && !DestType->isAggregateType()) {
|
2011-07-15 06:58:04 +08:00
|
|
|
Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
|
2011-09-25 01:48:00 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
InitListChecker CheckInitList(S, Entity, InitList,
|
|
|
|
DestType, /*VerifyOnly=*/true);
|
|
|
|
if (CheckInitList.HadError()) {
|
|
|
|
Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
|
|
|
|
return;
|
2011-07-15 06:58:04 +08:00
|
|
|
}
|
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
// Add the list initialization step with the built init list.
|
2011-07-15 06:58:04 +08:00
|
|
|
Sequence.AddListInitializationStep(DestType);
|
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
|
|
|
|
/// \brief Try a reference initialization that involves calling a conversion
|
|
|
|
/// function.
|
|
|
|
static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
|
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
Expr *Initializer,
|
|
|
|
bool AllowRValues,
|
|
|
|
InitializationSequence &Sequence) {
|
2009-12-22 23:35:07 +08:00
|
|
|
QualType DestType = Entity.getType();
|
2009-12-10 07:02:17 +08:00
|
|
|
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
|
|
|
|
QualType T1 = cv1T1.getUnqualifiedType();
|
|
|
|
QualType cv2T2 = Initializer->getType();
|
|
|
|
QualType T2 = cv2T2.getUnqualifiedType();
|
|
|
|
|
|
|
|
bool DerivedToBase;
|
2010-08-07 19:51:51 +08:00
|
|
|
bool ObjCConversion;
|
2011-06-16 07:02:42 +08:00
|
|
|
bool ObjCLifetimeConversion;
|
2011-01-27 15:10:08 +08:00
|
|
|
assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
|
2010-08-07 19:51:51 +08:00
|
|
|
T1, T2, DerivedToBase,
|
2011-06-16 07:02:42 +08:00
|
|
|
ObjCConversion,
|
|
|
|
ObjCLifetimeConversion) &&
|
2009-12-10 07:02:17 +08:00
|
|
|
"Must have incompatible references when binding via conversion");
|
2009-12-13 09:37:04 +08:00
|
|
|
(void)DerivedToBase;
|
2010-08-07 19:51:51 +08:00
|
|
|
(void)ObjCConversion;
|
2011-06-16 07:02:42 +08:00
|
|
|
(void)ObjCLifetimeConversion;
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Build the candidate set directly in the initialization sequence
|
|
|
|
// structure, so that it will persist if we fail.
|
|
|
|
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
|
|
|
|
CandidateSet.clear();
|
|
|
|
|
|
|
|
// Determine whether we are allowed to call explicit constructors or
|
|
|
|
// explicit conversion operators.
|
|
|
|
bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
const RecordType *T1RecordType = 0;
|
2010-05-08 03:42:26 +08:00
|
|
|
if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
|
|
|
|
!S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
|
2009-12-10 07:02:17 +08:00
|
|
|
// The type we're converting to is a class type. Enumerate its constructors
|
|
|
|
// to see if there is a suitable conversion.
|
|
|
|
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
|
2010-08-17 15:23:57 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
DeclContext::lookup_iterator Con, ConEnd;
|
2010-07-03 07:12:18 +08:00
|
|
|
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
|
2009-12-10 07:02:17 +08:00
|
|
|
Con != ConEnd; ++Con) {
|
2010-03-19 15:35:19 +08:00
|
|
|
NamedDecl *D = *Con;
|
|
|
|
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Find the constructor (which may be a template).
|
|
|
|
CXXConstructorDecl *Constructor = 0;
|
2010-03-19 15:35:19 +08:00
|
|
|
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
|
2009-12-10 07:02:17 +08:00
|
|
|
if (ConstructorTmpl)
|
|
|
|
Constructor = cast<CXXConstructorDecl>(
|
|
|
|
ConstructorTmpl->getTemplatedDecl());
|
|
|
|
else
|
2010-03-19 15:35:19 +08:00
|
|
|
Constructor = cast<CXXConstructorDecl>(D);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
if (!Constructor->isInvalidDecl() &&
|
|
|
|
Constructor->isConvertingConstructor(AllowExplicit)) {
|
|
|
|
if (ConstructorTmpl)
|
2010-03-19 15:35:19 +08:00
|
|
|
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
|
2010-01-26 09:37:31 +08:00
|
|
|
/*ExplicitArgs*/ 0,
|
2010-10-05 11:05:30 +08:00
|
|
|
&Initializer, 1, CandidateSet,
|
|
|
|
/*SuppressUserConversions=*/true);
|
2009-12-10 07:02:17 +08:00
|
|
|
else
|
2010-03-19 15:35:19 +08:00
|
|
|
S.AddOverloadCandidate(Constructor, FoundDecl,
|
2010-10-05 11:05:30 +08:00
|
|
|
&Initializer, 1, CandidateSet,
|
|
|
|
/*SuppressUserConversions=*/true);
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2010-08-17 15:23:57 +08:00
|
|
|
if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
|
|
|
|
return OR_No_Viable_Function;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-05-08 03:42:26 +08:00
|
|
|
const RecordType *T2RecordType = 0;
|
|
|
|
if ((T2RecordType = T2->getAs<RecordType>()) &&
|
|
|
|
!S.RequireCompleteType(Kind.getLocation(), T2, 0)) {
|
2009-12-10 07:02:17 +08:00
|
|
|
// The type we're converting from is a class type, enumerate its conversion
|
|
|
|
// functions.
|
|
|
|
CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
|
|
|
|
|
2010-01-20 08:46:10 +08:00
|
|
|
const UnresolvedSetImpl *Conversions
|
2009-12-10 07:02:17 +08:00
|
|
|
= T2RecordDecl->getVisibleConversionFunctions();
|
2010-01-20 08:46:10 +08:00
|
|
|
for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
|
|
|
|
E = Conversions->end(); I != E; ++I) {
|
2009-12-10 07:02:17 +08:00
|
|
|
NamedDecl *D = *I;
|
|
|
|
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
|
|
|
|
if (isa<UsingShadowDecl>(D))
|
|
|
|
D = cast<UsingShadowDecl>(D)->getTargetDecl();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
|
|
|
|
CXXConversionDecl *Conv;
|
|
|
|
if (ConvTemplate)
|
|
|
|
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
|
|
|
|
else
|
2010-07-01 02:13:39 +08:00
|
|
|
Conv = cast<CXXConversionDecl>(D);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// If the conversion function doesn't return a reference type,
|
|
|
|
// it can't be considered for this conversion unless we're allowed to
|
|
|
|
// consider rvalues.
|
2011-01-27 15:10:08 +08:00
|
|
|
// FIXME: Do we need to make sure that we only consider conversion
|
|
|
|
// candidates with reference-compatible results? That might be needed to
|
2009-12-10 07:02:17 +08:00
|
|
|
// break recursion.
|
|
|
|
if ((AllowExplicit || !Conv->isExplicit()) &&
|
|
|
|
(AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
|
|
|
|
if (ConvTemplate)
|
2010-03-19 15:35:19 +08:00
|
|
|
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
|
2010-01-26 09:37:31 +08:00
|
|
|
ActingDC, Initializer,
|
2011-01-21 08:27:08 +08:00
|
|
|
DestType, CandidateSet);
|
2009-12-10 07:02:17 +08:00
|
|
|
else
|
2010-03-19 15:35:19 +08:00
|
|
|
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
|
2011-01-21 08:27:08 +08:00
|
|
|
Initializer, DestType, CandidateSet);
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-08-17 15:23:57 +08:00
|
|
|
if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
|
|
|
|
return OR_No_Viable_Function;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
SourceLocation DeclLoc = Initializer->getLocStart();
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
// Perform overload resolution. If it fails, return the failed result.
|
2009-12-10 07:02:17 +08:00
|
|
|
OverloadCandidateSet::iterator Best;
|
2011-01-27 15:10:08 +08:00
|
|
|
if (OverloadingResult Result
|
2010-09-12 16:07:23 +08:00
|
|
|
= CandidateSet.BestViableFunction(S, DeclLoc, Best, true))
|
2009-12-10 07:02:17 +08:00
|
|
|
return Result;
|
2009-12-11 10:42:07 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
FunctionDecl *Function = Best->Function;
|
2009-12-11 10:42:07 +08:00
|
|
|
|
2011-02-26 03:41:05 +08:00
|
|
|
// This is the overload that will actually be used for the initialization, so
|
|
|
|
// mark it as used.
|
|
|
|
S.MarkDeclarationReferenced(DeclLoc, Function);
|
|
|
|
|
2009-12-11 10:42:07 +08:00
|
|
|
// Compute the returned type of the conversion.
|
2009-12-10 07:02:17 +08:00
|
|
|
if (isa<CXXConversionDecl>(Function))
|
|
|
|
T2 = Function->getResultType();
|
|
|
|
else
|
|
|
|
T2 = cv1T1;
|
2009-12-11 10:42:07 +08:00
|
|
|
|
|
|
|
// Add the user-defined conversion step.
|
2010-03-19 15:35:19 +08:00
|
|
|
Sequence.AddUserConversionStep(Function, Best->FoundDecl,
|
2010-07-14 02:40:04 +08:00
|
|
|
T2.getNonLValueExprType(S.Context));
|
2009-12-11 10:42:07 +08:00
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
// Determine whether we need to perform derived-to-base or
|
2009-12-11 10:42:07 +08:00
|
|
|
// cv-qualification adjustments.
|
2010-08-25 18:28:54 +08:00
|
|
|
ExprValueKind VK = VK_RValue;
|
2010-07-20 12:20:21 +08:00
|
|
|
if (T2->isLValueReferenceType())
|
2010-08-25 18:28:54 +08:00
|
|
|
VK = VK_LValue;
|
2010-07-20 12:20:21 +08:00
|
|
|
else if (const RValueReferenceType *RRef = T2->getAs<RValueReferenceType>())
|
2010-08-25 18:28:54 +08:00
|
|
|
VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue;
|
2010-07-20 12:20:21 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
bool NewDerivedToBase = false;
|
2010-08-07 19:51:51 +08:00
|
|
|
bool NewObjCConversion = false;
|
2011-06-16 07:02:42 +08:00
|
|
|
bool NewObjCLifetimeConversion = false;
|
2009-12-10 07:02:17 +08:00
|
|
|
Sema::ReferenceCompareResult NewRefRelationship
|
2011-01-27 15:10:08 +08:00
|
|
|
= S.CompareReferenceRelationship(DeclLoc, T1,
|
2010-07-14 02:40:04 +08:00
|
|
|
T2.getNonLValueExprType(S.Context),
|
2011-06-16 07:02:42 +08:00
|
|
|
NewDerivedToBase, NewObjCConversion,
|
|
|
|
NewObjCLifetimeConversion);
|
2010-03-08 07:17:44 +08:00
|
|
|
if (NewRefRelationship == Sema::Ref_Incompatible) {
|
|
|
|
// If the type we've converted to is not reference-related to the
|
|
|
|
// type we're looking for, then there is another conversion step
|
|
|
|
// we need to perform to produce a temporary of the right type
|
|
|
|
// that we'll be binding to.
|
|
|
|
ImplicitConversionSequence ICS;
|
|
|
|
ICS.setStandard();
|
|
|
|
ICS.Standard = Best->FinalConversion;
|
|
|
|
T2 = ICS.Standard.getToType(2);
|
|
|
|
Sequence.AddConversionSequenceStep(ICS, T2);
|
|
|
|
} else if (NewDerivedToBase)
|
2009-12-10 07:02:17 +08:00
|
|
|
Sequence.AddDerivedToBaseCastStep(
|
|
|
|
S.Context.getQualifiedType(T1,
|
2011-01-27 15:10:08 +08:00
|
|
|
T2.getNonReferenceType().getQualifiers()),
|
2010-08-25 18:28:54 +08:00
|
|
|
VK);
|
2010-08-07 19:51:51 +08:00
|
|
|
else if (NewObjCConversion)
|
|
|
|
Sequence.AddObjCObjectConversionStep(
|
|
|
|
S.Context.getQualifiedType(T1,
|
|
|
|
T2.getNonReferenceType().getQualifiers()));
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
|
2010-08-25 18:28:54 +08:00
|
|
|
Sequence.AddQualificationConversionStep(cv1T1, VK);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
|
|
|
|
return OR_Success;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
/// \brief Attempt reference initialization (C++0x [dcl.init.ref])
|
|
|
|
static void TryReferenceInitialization(Sema &S,
|
2009-12-10 07:02:17 +08:00
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
Expr *Initializer,
|
|
|
|
InitializationSequence &Sequence) {
|
2009-12-22 23:35:07 +08:00
|
|
|
QualType DestType = Entity.getType();
|
2009-12-10 07:02:17 +08:00
|
|
|
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
|
2010-01-13 04:32:25 +08:00
|
|
|
Qualifiers T1Quals;
|
|
|
|
QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals);
|
2009-12-10 07:02:17 +08:00
|
|
|
QualType cv2T2 = Initializer->getType();
|
2010-01-13 04:32:25 +08:00
|
|
|
Qualifiers T2Quals;
|
|
|
|
QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
|
2009-12-10 07:02:17 +08:00
|
|
|
SourceLocation DeclLoc = Initializer->getLocStart();
|
2010-07-01 02:13:39 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// If the initializer is the address of an overloaded function, try
|
|
|
|
// to resolve the overloaded function. If all goes well, T2 is the
|
|
|
|
// type of the resulting function.
|
|
|
|
if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
|
2010-03-31 05:47:33 +08:00
|
|
|
DeclAccessPair Found;
|
2011-01-27 15:10:08 +08:00
|
|
|
if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer,
|
2010-11-08 23:20:28 +08:00
|
|
|
T1,
|
|
|
|
false,
|
|
|
|
Found)) {
|
|
|
|
Sequence.AddAddressOverloadResolutionStep(Fn, Found);
|
|
|
|
cv2T2 = Fn->getType();
|
|
|
|
T2 = cv2T2.getUnqualifiedType();
|
|
|
|
} else if (!T1->isRecordType()) {
|
2009-12-10 07:02:17 +08:00
|
|
|
Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-07-01 02:13:39 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Compute some basic properties of the types and the initializer.
|
|
|
|
bool isLValueRef = DestType->isLValueReferenceType();
|
|
|
|
bool isRValueRef = !isLValueRef;
|
|
|
|
bool DerivedToBase = false;
|
2010-08-07 19:51:51 +08:00
|
|
|
bool ObjCConversion = false;
|
2011-06-16 07:02:42 +08:00
|
|
|
bool ObjCLifetimeConversion = false;
|
2010-07-01 02:13:39 +08:00
|
|
|
Expr::Classification InitCategory = Initializer->Classify(S.Context);
|
2009-12-10 07:02:17 +08:00
|
|
|
Sema::ReferenceCompareResult RefRelationship
|
2010-08-07 19:51:51 +08:00
|
|
|
= S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase,
|
2011-06-16 07:02:42 +08:00
|
|
|
ObjCConversion, ObjCLifetimeConversion);
|
2010-07-01 02:13:39 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// C++0x [dcl.init.ref]p5:
|
2011-01-27 15:10:08 +08:00
|
|
|
// A reference to type "cv1 T1" is initialized by an expression of type
|
2009-12-10 07:02:17 +08:00
|
|
|
// "cv2 T2" as follows:
|
|
|
|
//
|
2011-01-27 15:10:08 +08:00
|
|
|
// - If the reference is an lvalue reference and the initializer
|
2009-12-10 07:02:17 +08:00
|
|
|
// expression
|
2010-07-01 02:13:39 +08:00
|
|
|
// Note the analogous bullet points for rvlaue refs to functions. Because
|
|
|
|
// there are no function rvalues in C++, rvalue refs to functions are treated
|
|
|
|
// like lvalue refs.
|
2009-12-10 07:02:17 +08:00
|
|
|
OverloadingResult ConvOvlResult = OR_Success;
|
2010-07-01 02:13:39 +08:00
|
|
|
bool T1Function = T1->isFunctionType();
|
|
|
|
if (isLValueRef || T1Function) {
|
2011-01-27 15:10:08 +08:00
|
|
|
if (InitCategory.isLValue() &&
|
2011-01-27 08:58:17 +08:00
|
|
|
(RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
|
2011-01-27 15:10:08 +08:00
|
|
|
(Kind.isCStyleOrFunctionalCast() &&
|
2011-01-27 08:58:17 +08:00
|
|
|
RefRelationship == Sema::Ref_Related))) {
|
2011-01-27 15:10:08 +08:00
|
|
|
// - is an lvalue (but is not a bit-field), and "cv1 T1" is
|
2009-12-10 07:02:17 +08:00
|
|
|
// reference-compatible with "cv2 T2," or
|
|
|
|
//
|
2011-01-27 15:10:08 +08:00
|
|
|
// Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a
|
2009-12-10 07:02:17 +08:00
|
|
|
// bit-field when we're determining whether the reference initialization
|
2010-01-30 03:14:02 +08:00
|
|
|
// can occur. However, we do pay attention to whether it is a bit-field
|
|
|
|
// to decide whether we're actually binding to a temporary created from
|
|
|
|
// the bit-field.
|
2009-12-10 07:02:17 +08:00
|
|
|
if (DerivedToBase)
|
|
|
|
Sequence.AddDerivedToBaseCastStep(
|
2011-01-27 15:10:08 +08:00
|
|
|
S.Context.getQualifiedType(T1, T2Quals),
|
2010-08-25 18:28:54 +08:00
|
|
|
VK_LValue);
|
2010-08-07 19:51:51 +08:00
|
|
|
else if (ObjCConversion)
|
|
|
|
Sequence.AddObjCObjectConversionStep(
|
|
|
|
S.Context.getQualifiedType(T1, T2Quals));
|
|
|
|
|
2010-01-13 04:32:25 +08:00
|
|
|
if (T1Quals != T2Quals)
|
2010-08-25 18:28:54 +08:00
|
|
|
Sequence.AddQualificationConversionStep(cv1T1, VK_LValue);
|
2010-01-30 03:14:02 +08:00
|
|
|
bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
|
2010-02-01 01:18:49 +08:00
|
|
|
(Initializer->getBitField() || Initializer->refersToVectorElement());
|
2010-01-30 03:14:02 +08:00
|
|
|
Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// - has a class type (i.e., T2 is a class type), where T1 is not
|
|
|
|
// reference-related to T2, and can be implicitly converted to an
|
|
|
|
// lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible
|
|
|
|
// with "cv3 T3" (this conversion is selected by enumerating the
|
2009-12-10 07:02:17 +08:00
|
|
|
// applicable conversion functions (13.3.1.6) and choosing the best
|
|
|
|
// one through overload resolution (13.3)),
|
2010-07-01 02:13:39 +08:00
|
|
|
// If we have an rvalue ref to function type here, the rhs must be
|
|
|
|
// an rvalue.
|
|
|
|
if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() &&
|
|
|
|
(isLValueRef || InitCategory.isRValue())) {
|
2011-01-27 15:10:08 +08:00
|
|
|
ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
|
2009-12-10 07:02:17 +08:00
|
|
|
Initializer,
|
2010-07-01 02:13:39 +08:00
|
|
|
/*AllowRValues=*/isRValueRef,
|
2009-12-10 07:02:17 +08:00
|
|
|
Sequence);
|
|
|
|
if (ConvOvlResult == OR_Success)
|
|
|
|
return;
|
2010-01-12 08:44:57 +08:00
|
|
|
if (ConvOvlResult != OR_No_Viable_Function) {
|
|
|
|
Sequence.SetOverloadFailure(
|
|
|
|
InitializationSequence::FK_ReferenceInitOverloadFailed,
|
|
|
|
ConvOvlResult);
|
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
}
|
2010-07-01 02:13:39 +08:00
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
// - Otherwise, the reference shall be an lvalue reference to a
|
2009-12-10 07:02:17 +08:00
|
|
|
// non-volatile const type (i.e., cv1 shall be const), or the reference
|
2011-01-21 00:08:06 +08:00
|
|
|
// shall be an rvalue reference.
|
2011-01-21 08:52:42 +08:00
|
|
|
if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) {
|
2010-11-08 23:20:28 +08:00
|
|
|
if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
|
|
|
|
Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
|
|
|
|
else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
|
2009-12-10 07:02:17 +08:00
|
|
|
Sequence.SetOverloadFailure(
|
|
|
|
InitializationSequence::FK_ReferenceInitOverloadFailed,
|
|
|
|
ConvOvlResult);
|
2011-01-21 08:52:42 +08:00
|
|
|
else
|
2010-07-01 02:13:39 +08:00
|
|
|
Sequence.SetFailed(InitCategory.isLValue()
|
2009-12-10 07:02:17 +08:00
|
|
|
? (RefRelationship == Sema::Ref_Related
|
|
|
|
? InitializationSequence::FK_ReferenceInitDropsQualifiers
|
|
|
|
: InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
|
|
|
|
: InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
|
2010-07-01 02:13:39 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-07-01 02:13:39 +08:00
|
|
|
|
2011-01-21 00:44:54 +08:00
|
|
|
// - If the initializer expression
|
|
|
|
// - is an xvalue, class prvalue, array prvalue, or function lvalue and
|
|
|
|
// "cv1 T1" is reference-compatible with "cv2 T2"
|
|
|
|
// Note: functions are handled below.
|
|
|
|
if (!T1Function &&
|
2011-01-27 08:58:17 +08:00
|
|
|
(RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
|
2011-01-27 15:10:08 +08:00
|
|
|
(Kind.isCStyleOrFunctionalCast() &&
|
2011-01-27 08:58:17 +08:00
|
|
|
RefRelationship == Sema::Ref_Related)) &&
|
2011-01-21 00:44:54 +08:00
|
|
|
(InitCategory.isXValue() ||
|
|
|
|
(InitCategory.isPRValue() && T2->isRecordType()) ||
|
|
|
|
(InitCategory.isPRValue() && T2->isArrayType()))) {
|
|
|
|
ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue;
|
|
|
|
if (InitCategory.isPRValue() && T2->isRecordType()) {
|
2010-04-18 15:40:54 +08:00
|
|
|
// The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
|
|
|
|
// compiler the freedom to perform a copy here or bind to the
|
|
|
|
// object, while C++0x requires that we bind directly to the
|
|
|
|
// object. Hence, we always bind to the object without making an
|
|
|
|
// extra copy. However, in C++03 requires that we check for the
|
|
|
|
// presence of a suitable copy constructor:
|
|
|
|
//
|
|
|
|
// The constructor that would be used to make the copy shall
|
|
|
|
// be callable whether or not the copy is actually done.
|
2011-09-18 01:15:52 +08:00
|
|
|
if (!S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt)
|
2010-04-18 15:40:54 +08:00
|
|
|
Sequence.AddExtraneousCopyToTemporary(cv2T2);
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-01-21 00:44:54 +08:00
|
|
|
if (DerivedToBase)
|
|
|
|
Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals),
|
|
|
|
ValueKind);
|
|
|
|
else if (ObjCConversion)
|
|
|
|
Sequence.AddObjCObjectConversionStep(
|
|
|
|
S.Context.getQualifiedType(T1, T2Quals));
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-01-21 00:44:54 +08:00
|
|
|
if (T1Quals != T2Quals)
|
|
|
|
Sequence.AddQualificationConversionStep(cv1T1, ValueKind);
|
2011-01-27 15:10:08 +08:00
|
|
|
Sequence.AddReferenceBindingStep(cv1T1,
|
2011-01-21 00:44:54 +08:00
|
|
|
/*bindingTemporary=*/(InitCategory.isPRValue() && !T2->isArrayType()));
|
2011-01-27 15:10:08 +08:00
|
|
|
return;
|
2011-01-21 00:44:54 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// - has a class type (i.e., T2 is a class type), where T1 is not
|
|
|
|
// reference-related to T2, and can be implicitly converted to an
|
2011-01-21 00:44:54 +08:00
|
|
|
// xvalue, class prvalue, or function lvalue of type "cv3 T3",
|
|
|
|
// where "cv1 T1" is reference-compatible with "cv3 T3",
|
|
|
|
if (T2->isRecordType()) {
|
2009-12-10 07:02:17 +08:00
|
|
|
if (RefRelationship == Sema::Ref_Incompatible) {
|
|
|
|
ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
|
|
|
|
Kind, Initializer,
|
|
|
|
/*AllowRValues=*/true,
|
|
|
|
Sequence);
|
|
|
|
if (ConvOvlResult)
|
|
|
|
Sequence.SetOverloadFailure(
|
|
|
|
InitializationSequence::FK_ReferenceInitOverloadFailed,
|
|
|
|
ConvOvlResult);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
|
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:09:49 +08:00
|
|
|
|
|
|
|
// - Otherwise, a temporary of type "cv1 T1" is created and initialized
|
2009-12-10 07:02:17 +08:00
|
|
|
// from the initializer expression using the rules for a non-reference
|
2011-01-27 15:10:08 +08:00
|
|
|
// copy initialization (8.5). The reference is then bound to the
|
2009-12-10 07:02:17 +08:00
|
|
|
// temporary. [...]
|
2010-06-04 10:29:22 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Determine whether we are allowed to call explicit constructors or
|
|
|
|
// explicit conversion operators.
|
|
|
|
bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct);
|
2010-06-04 10:29:22 +08:00
|
|
|
|
|
|
|
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
ImplicitConversionSequence ICS
|
|
|
|
= S.TryImplicitConversion(Initializer, TempEntity.getType(),
|
2010-06-04 10:29:22 +08:00
|
|
|
/*SuppressUserConversions*/ false,
|
|
|
|
AllowExplicit,
|
2011-01-27 08:58:17 +08:00
|
|
|
/*FIXME:InOverloadResolution=*/false,
|
2011-06-16 07:02:42 +08:00
|
|
|
/*CStyle=*/Kind.isCStyleOrFunctionalCast(),
|
|
|
|
/*AllowObjCWritebackConversion=*/false);
|
|
|
|
|
|
|
|
if (ICS.isBad()) {
|
2009-12-10 07:02:17 +08:00
|
|
|
// FIXME: Use the conversion function set stored in ICS to turn
|
|
|
|
// this into an overloading ambiguity diagnostic. However, we need
|
|
|
|
// to keep that set as an OverloadCandidateSet rather than as some
|
|
|
|
// other kind of set.
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
|
|
|
|
Sequence.SetOverloadFailure(
|
|
|
|
InitializationSequence::FK_ReferenceInitOverloadFailed,
|
|
|
|
ConvOvlResult);
|
2010-11-08 23:20:28 +08:00
|
|
|
else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
|
|
|
|
Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
else
|
|
|
|
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
2011-06-16 07:02:42 +08:00
|
|
|
} else {
|
|
|
|
Sequence.AddConversionSequenceStep(ICS, TempEntity.getType());
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// [...] If T1 is reference-related to T2, cv1 must be the
|
|
|
|
// same cv-qualification as, or greater cv-qualification
|
|
|
|
// than, cv2; otherwise, the program is ill-formed.
|
2010-01-13 04:32:25 +08:00
|
|
|
unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
|
|
|
|
unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
|
2011-01-27 15:10:08 +08:00
|
|
|
if (RefRelationship == Sema::Ref_Related &&
|
2010-01-13 04:32:25 +08:00
|
|
|
(T1CVRQuals | T2CVRQuals) != T1CVRQuals) {
|
2009-12-10 07:02:17 +08:00
|
|
|
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
// [...] If T1 is reference-related to T2 and the reference is an rvalue
|
2011-01-21 08:52:42 +08:00
|
|
|
// reference, the initializer expression shall not be an lvalue.
|
2011-01-27 15:10:08 +08:00
|
|
|
if (RefRelationship >= Sema::Ref_Related && !isLValueRef &&
|
2011-01-21 08:52:42 +08:00
|
|
|
InitCategory.isLValue()) {
|
|
|
|
Sequence.SetFailed(
|
|
|
|
InitializationSequence::FK_RValueReferenceBindingToLValue);
|
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Attempt character array initialization from a string literal
|
2011-01-27 15:10:08 +08:00
|
|
|
/// (C++ [dcl.init.string], C99 6.7.8).
|
|
|
|
static void TryStringLiteralInitialization(Sema &S,
|
2009-12-10 07:02:17 +08:00
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
Expr *Initializer,
|
|
|
|
InitializationSequence &Sequence) {
|
2009-12-22 23:35:07 +08:00
|
|
|
Sequence.AddStringInitStep(Entity.getType());
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
|
|
|
|
/// enumerates the constructors of the initialized entity and performs overload
|
|
|
|
/// resolution to select the best.
|
2011-01-27 15:10:08 +08:00
|
|
|
static void TryConstructorInitialization(Sema &S,
|
2009-12-10 07:02:17 +08:00
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
Expr **Args, unsigned NumArgs,
|
2009-12-15 08:01:57 +08:00
|
|
|
QualType DestType,
|
2009-12-10 07:02:17 +08:00
|
|
|
InitializationSequence &Sequence) {
|
2011-09-02 05:44:13 +08:00
|
|
|
// Check constructor arguments for self reference.
|
|
|
|
if (DeclaratorDecl *DD = Entity.getDecl())
|
|
|
|
// Parameters arguments are occassionially constructed with itself,
|
|
|
|
// for instance, in recursive functions. Skip them.
|
|
|
|
if (!isa<ParmVarDecl>(DD))
|
|
|
|
for (unsigned i = 0; i < NumArgs; ++i)
|
|
|
|
S.CheckSelfReference(DD, Args[i]);
|
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
// Build the candidate set directly in the initialization sequence
|
|
|
|
// structure, so that it will persist if we fail.
|
|
|
|
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
|
|
|
|
CandidateSet.clear();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
// Determine whether we are allowed to call explicit constructors or
|
|
|
|
// explicit conversion operators.
|
|
|
|
bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
|
|
|
|
Kind.getKind() == InitializationKind::IK_Value ||
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
Kind.getKind() == InitializationKind::IK_Default);
|
2010-04-26 22:36:57 +08:00
|
|
|
|
|
|
|
// The type we're constructing needs to be complete.
|
|
|
|
if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
|
2010-05-21 06:12:02 +08:00
|
|
|
Sequence.SetFailed(InitializationSequence::FK_Incomplete);
|
2010-04-26 22:36:57 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
// The type we're converting to is a class type. Enumerate its constructors
|
|
|
|
// to see if one is suitable.
|
|
|
|
const RecordType *DestRecordType = DestType->getAs<RecordType>();
|
2011-01-27 15:10:08 +08:00
|
|
|
assert(DestRecordType && "Constructor initialization requires record type");
|
2009-12-15 04:49:26 +08:00
|
|
|
CXXRecordDecl *DestRecordDecl
|
|
|
|
= cast<CXXRecordDecl>(DestRecordType->getDecl());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
DeclContext::lookup_iterator Con, ConEnd;
|
2010-07-03 07:12:18 +08:00
|
|
|
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
|
2009-12-15 04:49:26 +08:00
|
|
|
Con != ConEnd; ++Con) {
|
2010-03-19 15:35:19 +08:00
|
|
|
NamedDecl *D = *Con;
|
|
|
|
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
|
2010-04-25 04:54:38 +08:00
|
|
|
bool SuppressUserConversions = false;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
// Find the constructor (which may be a template).
|
|
|
|
CXXConstructorDecl *Constructor = 0;
|
2010-03-19 15:35:19 +08:00
|
|
|
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
|
2009-12-15 04:49:26 +08:00
|
|
|
if (ConstructorTmpl)
|
|
|
|
Constructor = cast<CXXConstructorDecl>(
|
|
|
|
ConstructorTmpl->getTemplatedDecl());
|
2010-04-25 04:54:38 +08:00
|
|
|
else {
|
2010-03-19 15:35:19 +08:00
|
|
|
Constructor = cast<CXXConstructorDecl>(D);
|
2010-04-25 04:54:38 +08:00
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
// If we're performing copy initialization using a copy constructor, we
|
2010-04-25 04:54:38 +08:00
|
|
|
// suppress user-defined conversions on the arguments.
|
|
|
|
// FIXME: Move constructors?
|
|
|
|
if (Kind.getKind() == InitializationKind::IK_Copy &&
|
|
|
|
Constructor->isCopyConstructor())
|
|
|
|
SuppressUserConversions = true;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
if (!Constructor->isInvalidDecl() &&
|
2009-12-16 09:38:02 +08:00
|
|
|
(AllowExplicit || !Constructor->isExplicit())) {
|
2009-12-15 04:49:26 +08:00
|
|
|
if (ConstructorTmpl)
|
2010-03-19 15:35:19 +08:00
|
|
|
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
|
2010-01-26 09:37:31 +08:00
|
|
|
/*ExplicitArgs*/ 0,
|
2010-04-25 04:54:38 +08:00
|
|
|
Args, NumArgs, CandidateSet,
|
|
|
|
SuppressUserConversions);
|
2009-12-15 04:49:26 +08:00
|
|
|
else
|
2010-03-19 15:35:19 +08:00
|
|
|
S.AddOverloadCandidate(Constructor, FoundDecl,
|
2010-04-25 04:54:38 +08:00
|
|
|
Args, NumArgs, CandidateSet,
|
|
|
|
SuppressUserConversions);
|
2009-12-15 04:49:26 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
}
|
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
SourceLocation DeclLoc = Kind.getLocation();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// Perform overload resolution. If it fails, return the failed result.
|
2009-12-15 04:49:26 +08:00
|
|
|
OverloadCandidateSet::iterator Best;
|
2011-01-27 15:10:08 +08:00
|
|
|
if (OverloadingResult Result
|
2010-08-25 04:38:10 +08:00
|
|
|
= CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
|
2009-12-15 04:49:26 +08:00
|
|
|
Sequence.SetOverloadFailure(
|
2011-01-27 15:10:08 +08:00
|
|
|
InitializationSequence::FK_ConstructorOverloadFailed,
|
2009-12-15 04:49:26 +08:00
|
|
|
Result);
|
|
|
|
return;
|
|
|
|
}
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
|
|
|
|
// C++0x [dcl.init]p6:
|
|
|
|
// If a program calls for the default initialization of an object
|
|
|
|
// of a const-qualified type T, T shall be a class type with a
|
|
|
|
// user-provided default constructor.
|
|
|
|
if (Kind.getKind() == InitializationKind::IK_Default &&
|
|
|
|
Entity.getType().isConstQualified() &&
|
|
|
|
cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
|
|
|
|
Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
// Add the constructor initialization step. Any cv-qualification conversion is
|
|
|
|
// subsumed by the initialization.
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
Sequence.AddConstructorInitializationStep(
|
2011-01-27 15:10:08 +08:00
|
|
|
cast<CXXConstructorDecl>(Best->Function),
|
2010-03-19 15:35:19 +08:00
|
|
|
Best->FoundDecl.getAccess(),
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
DestType);
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
|
2009-12-15 08:01:57 +08:00
|
|
|
/// \brief Attempt value initialization (C++ [dcl.init]p7).
|
2011-01-27 15:10:08 +08:00
|
|
|
static void TryValueInitialization(Sema &S,
|
2009-12-15 08:01:57 +08:00
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
InitializationSequence &Sequence) {
|
|
|
|
// C++ [dcl.init]p5:
|
|
|
|
//
|
|
|
|
// To value-initialize an object of type T means:
|
2009-12-22 23:35:07 +08:00
|
|
|
QualType T = Entity.getType();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 08:01:57 +08:00
|
|
|
// -- if T is an array type, then each element is value-initialized;
|
|
|
|
while (const ArrayType *AT = S.Context.getAsArrayType(T))
|
|
|
|
T = AT->getElementType();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 08:01:57 +08:00
|
|
|
if (const RecordType *RT = T->getAs<RecordType>()) {
|
|
|
|
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
|
|
|
|
// -- if T is a class type (clause 9) with a user-declared
|
|
|
|
// constructor (12.1), then the default constructor for T is
|
|
|
|
// called (and the initialization is ill-formed if T has no
|
|
|
|
// accessible default constructor);
|
|
|
|
//
|
|
|
|
// FIXME: we really want to refer to a single subobject of the array,
|
|
|
|
// but Entity doesn't have a way to capture that (yet).
|
|
|
|
if (ClassDecl->hasUserDeclaredConstructor())
|
|
|
|
return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-17 02:50:27 +08:00
|
|
|
// -- if T is a (possibly cv-qualified) non-union class type
|
|
|
|
// without a user-provided constructor, then the object is
|
2011-01-27 15:09:49 +08:00
|
|
|
// zero-initialized and, if T's implicitly-declared default
|
2009-12-17 02:50:27 +08:00
|
|
|
// constructor is non-trivial, that constructor is called.
|
2010-05-12 05:36:43 +08:00
|
|
|
if ((ClassDecl->getTagKind() == TTK_Class ||
|
2010-07-08 14:14:04 +08:00
|
|
|
ClassDecl->getTagKind() == TTK_Struct)) {
|
2009-12-22 23:35:07 +08:00
|
|
|
Sequence.AddZeroInitializationStep(Entity.getType());
|
2011-01-27 15:10:08 +08:00
|
|
|
return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
|
2009-12-17 02:50:27 +08:00
|
|
|
}
|
2009-12-15 08:01:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-22 23:35:07 +08:00
|
|
|
Sequence.AddZeroInitializationStep(Entity.getType());
|
2009-12-15 08:01:57 +08:00
|
|
|
}
|
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
/// \brief Attempt default initialization (C++ [dcl.init]p6).
|
|
|
|
static void TryDefaultInitialization(Sema &S,
|
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
InitializationSequence &Sequence) {
|
|
|
|
assert(Kind.getKind() == InitializationKind::IK_Default);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
// C++ [dcl.init]p6:
|
|
|
|
// To default-initialize an object of type T means:
|
|
|
|
// - if T is an array type, each element is default-initialized;
|
2011-06-16 07:02:42 +08:00
|
|
|
QualType DestType = S.Context.getBaseElementType(Entity.getType());
|
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
// - if T is a (possibly cv-qualified) class type (Clause 9), the default
|
|
|
|
// constructor for T is called (and the initialization is ill-formed if
|
|
|
|
// T has no accessible default constructor);
|
2010-02-09 15:26:29 +08:00
|
|
|
if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) {
|
2010-08-23 15:55:51 +08:00
|
|
|
TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence);
|
|
|
|
return;
|
2009-12-16 09:38:02 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
// - otherwise, no initialization is performed.
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
// If a program calls for the default initialization of an object of
|
2011-01-27 15:10:08 +08:00
|
|
|
// a const-qualified type T, T shall be a class type with a user-provided
|
2009-12-16 09:38:02 +08:00
|
|
|
// default constructor.
|
2011-06-16 07:02:42 +08:00
|
|
|
if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus) {
|
2009-12-16 09:38:02 +08:00
|
|
|
Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
|
2011-06-16 07:02:42 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the destination type has a lifetime property, zero-initialize it.
|
|
|
|
if (DestType.getQualifiers().hasObjCLifetime()) {
|
|
|
|
Sequence.AddZeroInitializationStep(Entity.getType());
|
|
|
|
return;
|
|
|
|
}
|
2009-12-16 09:38:02 +08:00
|
|
|
}
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
|
|
|
|
/// which enumerates all conversion functions and performs overload resolution
|
|
|
|
/// to select the best.
|
2011-01-27 15:10:08 +08:00
|
|
|
static void TryUserDefinedConversion(Sema &S,
|
2009-12-10 07:02:17 +08:00
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
Expr *Initializer,
|
|
|
|
InitializationSequence &Sequence) {
|
2009-12-22 23:35:07 +08:00
|
|
|
QualType DestType = Entity.getType();
|
2009-12-15 01:27:33 +08:00
|
|
|
assert(!DestType->isReferenceType() && "References are handled elsewhere");
|
|
|
|
QualType SourceType = Initializer->getType();
|
|
|
|
assert((DestType->isRecordType() || SourceType->isRecordType()) &&
|
|
|
|
"Must have a class type to perform a user-defined conversion");
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 01:27:33 +08:00
|
|
|
// Build the candidate set directly in the initialization sequence
|
|
|
|
// structure, so that it will persist if we fail.
|
|
|
|
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
|
|
|
|
CandidateSet.clear();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 01:27:33 +08:00
|
|
|
// Determine whether we are allowed to call explicit constructors or
|
|
|
|
// explicit conversion operators.
|
|
|
|
bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 01:27:33 +08:00
|
|
|
if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) {
|
|
|
|
// The type we're converting to is a class type. Enumerate its constructors
|
|
|
|
// to see if there is a suitable conversion.
|
|
|
|
CXXRecordDecl *DestRecordDecl
|
|
|
|
= cast<CXXRecordDecl>(DestRecordType->getDecl());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-26 22:36:57 +08:00
|
|
|
// Try to complete the type we're converting to.
|
2011-01-27 15:10:08 +08:00
|
|
|
if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
|
2010-04-26 22:36:57 +08:00
|
|
|
DeclContext::lookup_iterator Con, ConEnd;
|
2010-07-03 07:12:18 +08:00
|
|
|
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
|
2010-04-26 22:36:57 +08:00
|
|
|
Con != ConEnd; ++Con) {
|
|
|
|
NamedDecl *D = *Con;
|
|
|
|
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-26 22:36:57 +08:00
|
|
|
// Find the constructor (which may be a template).
|
|
|
|
CXXConstructorDecl *Constructor = 0;
|
|
|
|
FunctionTemplateDecl *ConstructorTmpl
|
|
|
|
= dyn_cast<FunctionTemplateDecl>(D);
|
2009-12-15 01:27:33 +08:00
|
|
|
if (ConstructorTmpl)
|
2010-04-26 22:36:57 +08:00
|
|
|
Constructor = cast<CXXConstructorDecl>(
|
|
|
|
ConstructorTmpl->getTemplatedDecl());
|
2010-07-01 11:43:00 +08:00
|
|
|
else
|
2010-04-26 22:36:57 +08:00
|
|
|
Constructor = cast<CXXConstructorDecl>(D);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-26 22:36:57 +08:00
|
|
|
if (!Constructor->isInvalidDecl() &&
|
|
|
|
Constructor->isConvertingConstructor(AllowExplicit)) {
|
|
|
|
if (ConstructorTmpl)
|
|
|
|
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
|
|
|
|
/*ExplicitArgs*/ 0,
|
|
|
|
&Initializer, 1, CandidateSet,
|
2010-07-01 11:43:00 +08:00
|
|
|
/*SuppressUserConversions=*/true);
|
2010-04-26 22:36:57 +08:00
|
|
|
else
|
|
|
|
S.AddOverloadCandidate(Constructor, FoundDecl,
|
|
|
|
&Initializer, 1, CandidateSet,
|
2010-07-01 11:43:00 +08:00
|
|
|
/*SuppressUserConversions=*/true);
|
2010-04-26 22:36:57 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
}
|
2010-04-26 22:36:57 +08:00
|
|
|
}
|
2009-12-15 01:27:33 +08:00
|
|
|
}
|
2009-12-19 16:11:05 +08:00
|
|
|
|
|
|
|
SourceLocation DeclLoc = Initializer->getLocStart();
|
|
|
|
|
2009-12-15 01:27:33 +08:00
|
|
|
if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
|
|
|
|
// The type we're converting from is a class type, enumerate its conversion
|
|
|
|
// functions.
|
2009-12-19 16:11:05 +08:00
|
|
|
|
2009-12-21 06:12:03 +08:00
|
|
|
// We can only enumerate the conversion functions for a complete type; if
|
|
|
|
// the type isn't complete, simply skip this step.
|
|
|
|
if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) {
|
|
|
|
CXXRecordDecl *SourceRecordDecl
|
|
|
|
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-20 08:46:10 +08:00
|
|
|
const UnresolvedSetImpl *Conversions
|
2009-12-21 06:12:03 +08:00
|
|
|
= SourceRecordDecl->getVisibleConversionFunctions();
|
2010-01-20 08:46:10 +08:00
|
|
|
for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
|
2011-01-27 15:10:08 +08:00
|
|
|
E = Conversions->end();
|
2009-12-21 06:12:03 +08:00
|
|
|
I != E; ++I) {
|
|
|
|
NamedDecl *D = *I;
|
|
|
|
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
|
|
|
|
if (isa<UsingShadowDecl>(D))
|
|
|
|
D = cast<UsingShadowDecl>(D)->getTargetDecl();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-21 06:12:03 +08:00
|
|
|
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
|
|
|
|
CXXConversionDecl *Conv;
|
2009-12-15 01:27:33 +08:00
|
|
|
if (ConvTemplate)
|
2009-12-21 06:12:03 +08:00
|
|
|
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
|
2009-12-15 01:27:33 +08:00
|
|
|
else
|
2010-03-31 09:36:47 +08:00
|
|
|
Conv = cast<CXXConversionDecl>(D);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-21 06:12:03 +08:00
|
|
|
if (AllowExplicit || !Conv->isExplicit()) {
|
|
|
|
if (ConvTemplate)
|
2010-03-19 15:35:19 +08:00
|
|
|
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
|
2010-01-26 09:37:31 +08:00
|
|
|
ActingDC, Initializer, DestType,
|
2009-12-21 06:12:03 +08:00
|
|
|
CandidateSet);
|
|
|
|
else
|
2010-03-19 15:35:19 +08:00
|
|
|
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
|
2010-01-26 09:37:31 +08:00
|
|
|
Initializer, DestType, CandidateSet);
|
2009-12-21 06:12:03 +08:00
|
|
|
}
|
2009-12-15 01:27:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// Perform overload resolution. If it fails, return the failed result.
|
2009-12-15 01:27:33 +08:00
|
|
|
OverloadCandidateSet::iterator Best;
|
2010-01-12 08:44:57 +08:00
|
|
|
if (OverloadingResult Result
|
2010-09-12 16:07:23 +08:00
|
|
|
= CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
|
2009-12-15 01:27:33 +08:00
|
|
|
Sequence.SetOverloadFailure(
|
2011-01-27 15:10:08 +08:00
|
|
|
InitializationSequence::FK_UserConversionOverloadFailed,
|
2009-12-15 01:27:33 +08:00
|
|
|
Result);
|
|
|
|
return;
|
|
|
|
}
|
2010-01-12 08:44:57 +08:00
|
|
|
|
2009-12-15 01:27:33 +08:00
|
|
|
FunctionDecl *Function = Best->Function;
|
2011-02-26 03:41:05 +08:00
|
|
|
S.MarkDeclarationReferenced(DeclLoc, Function);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 01:27:33 +08:00
|
|
|
if (isa<CXXConstructorDecl>(Function)) {
|
|
|
|
// Add the user-defined conversion step. Any cv-qualification conversion is
|
|
|
|
// subsumed by the initialization.
|
2010-03-19 15:35:19 +08:00
|
|
|
Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType);
|
2009-12-15 01:27:33 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the user-defined conversion step that calls the conversion function.
|
2010-07-13 16:18:22 +08:00
|
|
|
QualType ConvType = Function->getCallResultType();
|
2010-04-18 06:01:05 +08:00
|
|
|
if (ConvType->getAs<RecordType>()) {
|
|
|
|
// If we're converting to a class type, there may be an copy if
|
|
|
|
// the resulting temporary object (possible to create an object of
|
|
|
|
// a base class type). That copy is not a separate conversion, so
|
|
|
|
// we just make a note of the actual destination type (possibly a
|
|
|
|
// base class of the type returned by the conversion function) and
|
|
|
|
// let the user-defined conversion step handle the conversion.
|
|
|
|
Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType);
|
|
|
|
return;
|
|
|
|
}
|
2009-12-15 01:27:33 +08:00
|
|
|
|
2010-04-18 06:01:05 +08:00
|
|
|
Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-18 06:01:05 +08:00
|
|
|
// If the conversion following the call to the conversion function
|
|
|
|
// is interesting, add it as a separate step.
|
2009-12-15 01:27:33 +08:00
|
|
|
if (Best->FinalConversion.First || Best->FinalConversion.Second ||
|
|
|
|
Best->FinalConversion.Third) {
|
|
|
|
ImplicitConversionSequence ICS;
|
2010-01-12 08:44:57 +08:00
|
|
|
ICS.setStandard();
|
2009-12-15 01:27:33 +08:00
|
|
|
ICS.Standard = Best->FinalConversion;
|
|
|
|
Sequence.AddConversionSequenceStep(ICS, DestType);
|
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
/// The non-zero enum values here are indexes into diagnostic alternatives.
|
|
|
|
enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar };
|
|
|
|
|
|
|
|
/// Determines whether this expression is an acceptable ICR source.
|
2011-06-28 07:59:58 +08:00
|
|
|
static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
|
|
|
|
bool isAddressOf) {
|
2011-06-16 07:02:42 +08:00
|
|
|
// Skip parens.
|
|
|
|
e = e->IgnoreParens();
|
|
|
|
|
|
|
|
// Skip address-of nodes.
|
|
|
|
if (UnaryOperator *op = dyn_cast<UnaryOperator>(e)) {
|
|
|
|
if (op->getOpcode() == UO_AddrOf)
|
2011-06-28 07:59:58 +08:00
|
|
|
return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true);
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
// Skip certain casts.
|
2011-06-28 07:59:58 +08:00
|
|
|
} else if (CastExpr *ce = dyn_cast<CastExpr>(e)) {
|
|
|
|
switch (ce->getCastKind()) {
|
2011-06-16 07:02:42 +08:00
|
|
|
case CK_Dependent:
|
|
|
|
case CK_BitCast:
|
|
|
|
case CK_LValueBitCast:
|
|
|
|
case CK_NoOp:
|
2011-06-28 07:59:58 +08:00
|
|
|
return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf);
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
case CK_ArrayToPointerDecay:
|
|
|
|
return IIK_nonscalar;
|
|
|
|
|
|
|
|
case CK_NullToPointer:
|
|
|
|
return IIK_okay;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have a declaration reference, it had better be a local variable.
|
2011-06-28 07:59:58 +08:00
|
|
|
} else if (isa<DeclRefExpr>(e) || isa<BlockDeclRefExpr>(e)) {
|
|
|
|
if (!isAddressOf) return IIK_nonlocal;
|
|
|
|
|
|
|
|
VarDecl *var;
|
|
|
|
if (isa<DeclRefExpr>(e)) {
|
|
|
|
var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl());
|
|
|
|
if (!var) return IIK_nonlocal;
|
|
|
|
} else {
|
|
|
|
var = cast<BlockDeclRefExpr>(e)->getDecl();
|
|
|
|
}
|
|
|
|
|
|
|
|
return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal);
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
// If we have a conditional operator, check both sides.
|
|
|
|
} else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) {
|
2011-06-28 07:59:58 +08:00
|
|
|
if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf))
|
2011-06-16 07:02:42 +08:00
|
|
|
return iik;
|
|
|
|
|
2011-06-28 07:59:58 +08:00
|
|
|
return isInvalidICRSource(C, cond->getRHS(), isAddressOf);
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
// These are never scalar.
|
|
|
|
} else if (isa<ArraySubscriptExpr>(e)) {
|
|
|
|
return IIK_nonscalar;
|
|
|
|
|
|
|
|
// Otherwise, it needs to be a null pointer constant.
|
|
|
|
} else {
|
|
|
|
return (e->isNullPointerConstant(C, Expr::NPC_ValueDependentIsNull)
|
|
|
|
? IIK_okay : IIK_nonlocal);
|
|
|
|
}
|
|
|
|
|
|
|
|
return IIK_nonlocal;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Check whether the given expression is a valid operand for an
|
|
|
|
/// indirect copy/restore.
|
|
|
|
static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
|
|
|
|
assert(src->isRValue());
|
|
|
|
|
2011-06-28 07:59:58 +08:00
|
|
|
InvalidICRKind iik = isInvalidICRSource(S.Context, src, false);
|
2011-06-16 07:02:42 +08:00
|
|
|
if (iik == IIK_okay) return;
|
|
|
|
|
|
|
|
S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback)
|
|
|
|
<< ((unsigned) iik - 1) // shift index into diagnostic explanations
|
|
|
|
<< src->getSourceRange();
|
|
|
|
}
|
|
|
|
|
2011-02-23 02:29:51 +08:00
|
|
|
/// \brief Determine whether we have compatible array types for the
|
|
|
|
/// purposes of GNU by-copy array initialization.
|
|
|
|
static bool hasCompatibleArrayTypes(ASTContext &Context,
|
|
|
|
const ArrayType *Dest,
|
|
|
|
const ArrayType *Source) {
|
|
|
|
// If the source and destination array types are equivalent, we're
|
|
|
|
// done.
|
|
|
|
if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0)))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Make sure that the element types are the same.
|
|
|
|
if (!Context.hasSameType(Dest->getElementType(), Source->getElementType()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// The only mismatch we allow is when the destination is an
|
|
|
|
// incomplete array type and the source is a constant array type.
|
|
|
|
return Source->isConstantArrayType() && Dest->isIncompleteArrayType();
|
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
static bool tryObjCWritebackConversion(Sema &S,
|
|
|
|
InitializationSequence &Sequence,
|
|
|
|
const InitializedEntity &Entity,
|
|
|
|
Expr *Initializer) {
|
|
|
|
bool ArrayDecay = false;
|
|
|
|
QualType ArgType = Initializer->getType();
|
|
|
|
QualType ArgPointee;
|
|
|
|
if (const ArrayType *ArgArrayType = S.Context.getAsArrayType(ArgType)) {
|
|
|
|
ArrayDecay = true;
|
|
|
|
ArgPointee = ArgArrayType->getElementType();
|
|
|
|
ArgType = S.Context.getPointerType(ArgPointee);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle write-back conversion.
|
|
|
|
QualType ConvertedArgType;
|
|
|
|
if (!S.isObjCWritebackConversion(ArgType, Entity.getType(),
|
|
|
|
ConvertedArgType))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We should copy unless we're passing to an argument explicitly
|
|
|
|
// marked 'out'.
|
|
|
|
bool ShouldCopy = true;
|
|
|
|
if (ParmVarDecl *param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
|
|
|
|
ShouldCopy = (param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);
|
|
|
|
|
|
|
|
// Do we need an lvalue conversion?
|
|
|
|
if (ArrayDecay || Initializer->isGLValue()) {
|
|
|
|
ImplicitConversionSequence ICS;
|
|
|
|
ICS.setStandard();
|
|
|
|
ICS.Standard.setAsIdentityConversion();
|
|
|
|
|
|
|
|
QualType ResultType;
|
|
|
|
if (ArrayDecay) {
|
|
|
|
ICS.Standard.First = ICK_Array_To_Pointer;
|
|
|
|
ResultType = S.Context.getPointerType(ArgPointee);
|
|
|
|
} else {
|
|
|
|
ICS.Standard.First = ICK_Lvalue_To_Rvalue;
|
|
|
|
ResultType = Initializer->getType().getNonLValueExprType(S.Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sequence.AddConversionSequenceStep(ICS, ResultType);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
InitializationSequence::InitializationSequence(Sema &S,
|
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
Expr **Args,
|
2010-02-09 07:07:23 +08:00
|
|
|
unsigned NumArgs)
|
|
|
|
: FailedCandidateSet(Kind.getLocation()) {
|
2011-07-15 06:58:04 +08:00
|
|
|
ASTContext &Context = S.Context;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// C++0x [dcl.init]p16:
|
2011-01-27 15:10:08 +08:00
|
|
|
// The semantics of initializers are as follows. The destination type is
|
|
|
|
// the type of the object or reference being initialized and the source
|
2009-12-10 07:02:17 +08:00
|
|
|
// type is the type of the initializer expression. The source type is not
|
2011-01-27 15:10:08 +08:00
|
|
|
// defined when the initializer is a braced-init-list or when it is a
|
2009-12-10 07:02:17 +08:00
|
|
|
// parenthesized list of expressions.
|
2011-07-15 06:58:04 +08:00
|
|
|
QualType DestType = Entity.getType();
|
2009-12-10 07:02:17 +08:00
|
|
|
|
2011-07-15 06:58:04 +08:00
|
|
|
if (DestType->isDependentType() ||
|
2009-12-10 07:02:17 +08:00
|
|
|
Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
|
|
|
|
SequenceKind = DependentSequence;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-06-05 21:59:11 +08:00
|
|
|
// Almost everything is a normal sequence.
|
|
|
|
setSequenceKind(NormalSequence);
|
|
|
|
|
2010-12-08 06:54:16 +08:00
|
|
|
for (unsigned I = 0; I != NumArgs; ++I)
|
2011-04-09 02:41:53 +08:00
|
|
|
if (Args[I]->getObjectKind() == OK_ObjCProperty) {
|
|
|
|
ExprResult Result = S.ConvertPropertyForRValue(Args[I]);
|
|
|
|
if (Result.isInvalid()) {
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(FK_ConversionFromPropertyFailed);
|
2011-04-09 02:41:53 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Args[I] = Result.take();
|
|
|
|
}
|
2010-12-08 06:54:16 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
QualType SourceType;
|
|
|
|
Expr *Initializer = 0;
|
2009-12-16 09:38:02 +08:00
|
|
|
if (NumArgs == 1) {
|
2009-12-10 07:02:17 +08:00
|
|
|
Initializer = Args[0];
|
|
|
|
if (!isa<InitListExpr>(Initializer))
|
|
|
|
SourceType = Initializer->getType();
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// - If the initializer is a braced-init-list, the object is
|
2009-12-10 07:02:17 +08:00
|
|
|
// list-initialized (8.5.4).
|
|
|
|
if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
|
2011-07-15 06:58:04 +08:00
|
|
|
TryListInitialization(S, Entity, Kind, InitList, *this);
|
2009-12-11 01:56:55 +08:00
|
|
|
return;
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// - If the destination type is a reference type, see 8.5.3.
|
|
|
|
if (DestType->isReferenceType()) {
|
|
|
|
// C++0x [dcl.init.ref]p1:
|
|
|
|
// A variable declared to be a T& or T&&, that is, "reference to type T"
|
|
|
|
// (8.3.2), shall be initialized by an object, or function, of type T or
|
|
|
|
// by an object that can be converted into a T.
|
|
|
|
// (Therefore, multiple arguments are not permitted.)
|
|
|
|
if (NumArgs != 1)
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(FK_TooManyInitsForReference);
|
2009-12-10 07:02:17 +08:00
|
|
|
else
|
2011-07-15 06:58:04 +08:00
|
|
|
TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// - If the initializer is (), the object is value-initialized.
|
2009-12-16 09:38:02 +08:00
|
|
|
if (Kind.getKind() == InitializationKind::IK_Value ||
|
|
|
|
(Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
|
2011-07-15 06:58:04 +08:00
|
|
|
TryValueInitialization(S, Entity, Kind, *this);
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
// Handle default initialization.
|
2010-11-20 09:29:55 +08:00
|
|
|
if (Kind.getKind() == InitializationKind::IK_Default) {
|
2011-07-15 06:58:04 +08:00
|
|
|
TryDefaultInitialization(S, Entity, Kind, *this);
|
2009-12-16 09:38:02 +08:00
|
|
|
return;
|
|
|
|
}
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
|
2011-02-21 15:22:22 +08:00
|
|
|
// - If the destination type is an array of characters, an array of
|
|
|
|
// char16_t, an array of char32_t, or an array of wchar_t, and the
|
|
|
|
// initializer is a string literal, see 8.5.2.
|
2011-01-27 15:10:08 +08:00
|
|
|
// - Otherwise, if the destination type is an array, the program is
|
2009-12-10 07:02:17 +08:00
|
|
|
// ill-formed.
|
2011-02-23 02:29:51 +08:00
|
|
|
if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) {
|
|
|
|
if (Initializer && IsStringInit(Initializer, DestAT, Context)) {
|
2011-07-15 06:58:04 +08:00
|
|
|
TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
|
2011-02-21 15:22:22 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-02-23 02:29:51 +08:00
|
|
|
// Note: as an GNU C extension, we allow initialization of an
|
|
|
|
// array from a compound literal that creates an array of the same
|
|
|
|
// type, so long as the initializer has no side effects.
|
|
|
|
if (!S.getLangOptions().CPlusPlus && Initializer &&
|
|
|
|
isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
|
|
|
|
Initializer->getType()->isArrayType()) {
|
|
|
|
const ArrayType *SourceAT
|
|
|
|
= Context.getAsArrayType(Initializer->getType());
|
|
|
|
if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT))
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(FK_ArrayTypeMismatch);
|
2011-02-23 02:29:51 +08:00
|
|
|
else if (Initializer->HasSideEffects(S.Context))
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(FK_NonConstantArrayInit);
|
2011-02-23 02:29:51 +08:00
|
|
|
else {
|
2011-07-15 06:58:04 +08:00
|
|
|
AddArrayInitStep(DestType);
|
2011-02-23 02:29:51 +08:00
|
|
|
}
|
|
|
|
} else if (DestAT->getElementType()->isAnyCharacterType())
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
|
2009-12-10 07:02:17 +08:00
|
|
|
else
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(FK_ArrayNeedsInitList);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-12-19 16:11:05 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
// Determine whether we should consider writeback conversions for
|
|
|
|
// Objective-C ARC.
|
|
|
|
bool allowObjCWritebackConversion = S.getLangOptions().ObjCAutoRefCount &&
|
|
|
|
Entity.getKind() == InitializedEntity::EK_Parameter;
|
|
|
|
|
|
|
|
// We're at the end of the line for C: it's either a write-back conversion
|
|
|
|
// or it's a C assignment. There's no need to check anything else.
|
2009-12-19 16:11:05 +08:00
|
|
|
if (!S.getLangOptions().CPlusPlus) {
|
2011-06-16 07:02:42 +08:00
|
|
|
// If allowed, check whether this is an Objective-C writeback conversion.
|
|
|
|
if (allowObjCWritebackConversion &&
|
2011-07-15 06:58:04 +08:00
|
|
|
tryObjCWritebackConversion(S, *this, Entity, Initializer)) {
|
2011-06-16 07:02:42 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle initialization in C
|
2011-07-15 06:58:04 +08:00
|
|
|
AddCAssignmentStep(DestType);
|
|
|
|
MaybeProduceObjCObject(S, *this, Entity);
|
2009-12-19 16:11:05 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
assert(S.getLangOptions().CPlusPlus);
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// - If the destination type is a (possibly cv-qualified) class type:
|
|
|
|
if (DestType->isRecordType()) {
|
2011-01-27 15:10:08 +08:00
|
|
|
// - If the initialization is direct-initialization, or if it is
|
|
|
|
// copy-initialization where the cv-unqualified version of the
|
|
|
|
// source type is the same class as, or a derived class of, the
|
2009-12-10 07:02:17 +08:00
|
|
|
// class of the destination, constructors are considered. [...]
|
|
|
|
if (Kind.getKind() == InitializationKind::IK_Direct ||
|
|
|
|
(Kind.getKind() == InitializationKind::IK_Copy &&
|
|
|
|
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
|
|
|
|
S.IsDerivedFrom(SourceType, DestType))))
|
2011-01-27 15:10:08 +08:00
|
|
|
TryConstructorInitialization(S, Entity, Kind, Args, NumArgs,
|
2011-07-15 06:58:04 +08:00
|
|
|
Entity.getType(), *this);
|
2011-01-27 15:10:08 +08:00
|
|
|
// - Otherwise (i.e., for the remaining copy-initialization cases),
|
2009-12-10 07:02:17 +08:00
|
|
|
// user-defined conversion sequences that can convert from the source
|
2011-01-27 15:10:08 +08:00
|
|
|
// type to the destination type or (when a conversion function is
|
2009-12-10 07:02:17 +08:00
|
|
|
// used) to a derived class thereof are enumerated as described in
|
|
|
|
// 13.3.1.4, and the best one is chosen through overload resolution
|
|
|
|
// (13.3).
|
|
|
|
else
|
2011-07-15 06:58:04 +08:00
|
|
|
TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
if (NumArgs > 1) {
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(FK_TooManyInitsForScalar);
|
2009-12-16 09:38:02 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
assert(NumArgs == 1 && "Zero-argument case handled above");
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// - Otherwise, if the source type is a (possibly cv-qualified) class
|
2009-12-10 07:02:17 +08:00
|
|
|
// type, conversion functions are considered.
|
2009-12-16 09:38:02 +08:00
|
|
|
if (!SourceType.isNull() && SourceType->isRecordType()) {
|
2011-07-15 06:58:04 +08:00
|
|
|
TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
|
|
|
|
MaybeProduceObjCObject(S, *this, Entity);
|
2009-12-10 07:02:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// - Otherwise, the initial value of the object being initialized is the
|
2009-12-15 01:27:33 +08:00
|
|
|
// (possibly converted) value of the initializer expression. Standard
|
2009-12-10 07:02:17 +08:00
|
|
|
// conversions (Clause 4) will be used, if necessary, to convert the
|
2011-01-27 15:10:08 +08:00
|
|
|
// initializer expression to the cv-unqualified version of the
|
2009-12-10 07:02:17 +08:00
|
|
|
// destination type; no user-defined conversions are considered.
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
ImplicitConversionSequence ICS
|
|
|
|
= S.TryImplicitConversion(Initializer, Entity.getType(),
|
|
|
|
/*SuppressUserConversions*/true,
|
2010-06-04 10:29:22 +08:00
|
|
|
/*AllowExplicitConversions*/ false,
|
2011-01-27 08:58:17 +08:00
|
|
|
/*InOverloadResolution*/ false,
|
2011-06-16 07:02:42 +08:00
|
|
|
/*CStyle=*/Kind.isCStyleOrFunctionalCast(),
|
|
|
|
allowObjCWritebackConversion);
|
|
|
|
|
|
|
|
if (ICS.isStandard() &&
|
|
|
|
ICS.Standard.Second == ICK_Writeback_Conversion) {
|
|
|
|
// Objective-C ARC writeback conversion.
|
|
|
|
|
|
|
|
// We should copy unless we're passing to an argument explicitly
|
|
|
|
// marked 'out'.
|
|
|
|
bool ShouldCopy = true;
|
|
|
|
if (ParmVarDecl *Param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
|
|
|
|
ShouldCopy = (Param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);
|
|
|
|
|
|
|
|
// If there was an lvalue adjustment, add it as a separate conversion.
|
|
|
|
if (ICS.Standard.First == ICK_Array_To_Pointer ||
|
|
|
|
ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
|
|
|
|
ImplicitConversionSequence LvalueICS;
|
|
|
|
LvalueICS.setStandard();
|
|
|
|
LvalueICS.Standard.setAsIdentityConversion();
|
|
|
|
LvalueICS.Standard.setAllToTypes(ICS.Standard.getToType(0));
|
|
|
|
LvalueICS.Standard.First = ICS.Standard.First;
|
2011-07-15 06:58:04 +08:00
|
|
|
AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2011-07-15 06:58:04 +08:00
|
|
|
|
|
|
|
AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
|
2011-06-16 07:02:42 +08:00
|
|
|
} else if (ICS.isBad()) {
|
2011-02-20 05:32:49 +08:00
|
|
|
DeclAccessPair dap;
|
|
|
|
if (Initializer->getType() == Context.OverloadTy &&
|
|
|
|
!S.ResolveAddressOfOverloadedFunction(Initializer
|
|
|
|
, DestType, false, dap))
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
|
2010-11-08 11:40:48 +08:00
|
|
|
else
|
2011-07-15 06:58:04 +08:00
|
|
|
SetFailed(InitializationSequence::FK_ConversionFailed);
|
2011-06-16 07:02:42 +08:00
|
|
|
} else {
|
2011-07-15 06:58:04 +08:00
|
|
|
AddConversionSequenceStep(ICS, Entity.getType());
|
2011-06-17 07:24:51 +08:00
|
|
|
|
2011-07-15 06:58:04 +08:00
|
|
|
MaybeProduceObjCObject(S, *this, Entity);
|
2010-11-08 11:40:48 +08:00
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
InitializationSequence::~InitializationSequence() {
|
2011-07-23 18:55:15 +08:00
|
|
|
for (SmallVectorImpl<Step>::iterator Step = Steps.begin(),
|
2009-12-10 07:02:17 +08:00
|
|
|
StepEnd = Steps.end();
|
|
|
|
Step != StepEnd; ++Step)
|
|
|
|
Step->Destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Perform initialization
|
|
|
|
//===----------------------------------------------------------------------===//
|
2011-01-27 15:10:08 +08:00
|
|
|
static Sema::AssignmentAction
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
getAssignmentAction(const InitializedEntity &Entity) {
|
|
|
|
switch(Entity.getKind()) {
|
|
|
|
case InitializedEntity::EK_Variable:
|
|
|
|
case InitializedEntity::EK_New:
|
2010-12-03 05:47:04 +08:00
|
|
|
case InitializedEntity::EK_Exception:
|
|
|
|
case InitializedEntity::EK_Base:
|
2011-05-01 15:04:31 +08:00
|
|
|
case InitializedEntity::EK_Delegating:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
return Sema::AA_Initializing;
|
|
|
|
|
|
|
|
case InitializedEntity::EK_Parameter:
|
2011-01-27 15:10:08 +08:00
|
|
|
if (Entity.getDecl() &&
|
2010-04-22 07:24:10 +08:00
|
|
|
isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
|
|
|
|
return Sema::AA_Sending;
|
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
return Sema::AA_Passing;
|
|
|
|
|
|
|
|
case InitializedEntity::EK_Result:
|
|
|
|
return Sema::AA_Returning;
|
|
|
|
|
|
|
|
case InitializedEntity::EK_Temporary:
|
|
|
|
// FIXME: Can we tell apart casting vs. converting?
|
|
|
|
return Sema::AA_Casting;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case InitializedEntity::EK_Member:
|
2010-01-23 12:34:47 +08:00
|
|
|
case InitializedEntity::EK_ArrayElement:
|
|
|
|
case InitializedEntity::EK_VectorElement:
|
2011-09-20 07:17:44 +08:00
|
|
|
case InitializedEntity::EK_ComplexElement:
|
2010-06-08 00:14:00 +08:00
|
|
|
case InitializedEntity::EK_BlockElement:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
return Sema::AA_Initializing;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Sema::AA_Converting;
|
|
|
|
}
|
|
|
|
|
2010-04-25 07:45:46 +08:00
|
|
|
/// \brief Whether we should binding a created object as a temporary when
|
|
|
|
/// initializing the given entity.
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
switch (Entity.getKind()) {
|
2010-01-24 08:19:41 +08:00
|
|
|
case InitializedEntity::EK_ArrayElement:
|
|
|
|
case InitializedEntity::EK_Member:
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
case InitializedEntity::EK_Result:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case InitializedEntity::EK_New:
|
|
|
|
case InitializedEntity::EK_Variable:
|
|
|
|
case InitializedEntity::EK_Base:
|
2011-05-01 15:04:31 +08:00
|
|
|
case InitializedEntity::EK_Delegating:
|
2010-01-23 12:34:47 +08:00
|
|
|
case InitializedEntity::EK_VectorElement:
|
2011-09-20 07:17:44 +08:00
|
|
|
case InitializedEntity::EK_ComplexElement:
|
2010-02-07 07:23:06 +08:00
|
|
|
case InitializedEntity::EK_Exception:
|
2010-06-08 00:14:00 +08:00
|
|
|
case InitializedEntity::EK_BlockElement:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
return false;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case InitializedEntity::EK_Parameter:
|
|
|
|
case InitializedEntity::EK_Temporary:
|
|
|
|
return true;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
llvm_unreachable("missed an InitializedEntity kind?");
|
|
|
|
}
|
|
|
|
|
2010-04-25 07:45:46 +08:00
|
|
|
/// \brief Whether the given entity, when initialized with an object
|
|
|
|
/// created for that initialization, requires destruction.
|
|
|
|
static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
|
|
|
|
switch (Entity.getKind()) {
|
|
|
|
case InitializedEntity::EK_Member:
|
|
|
|
case InitializedEntity::EK_Result:
|
|
|
|
case InitializedEntity::EK_New:
|
|
|
|
case InitializedEntity::EK_Base:
|
2011-05-01 15:04:31 +08:00
|
|
|
case InitializedEntity::EK_Delegating:
|
2010-04-25 07:45:46 +08:00
|
|
|
case InitializedEntity::EK_VectorElement:
|
2011-09-20 07:17:44 +08:00
|
|
|
case InitializedEntity::EK_ComplexElement:
|
2010-06-08 00:14:00 +08:00
|
|
|
case InitializedEntity::EK_BlockElement:
|
2010-04-25 07:45:46 +08:00
|
|
|
return false;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-25 07:45:46 +08:00
|
|
|
case InitializedEntity::EK_Variable:
|
|
|
|
case InitializedEntity::EK_Parameter:
|
|
|
|
case InitializedEntity::EK_Temporary:
|
|
|
|
case InitializedEntity::EK_ArrayElement:
|
|
|
|
case InitializedEntity::EK_Exception:
|
|
|
|
return true;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
llvm_unreachable("missed an InitializedEntity kind?");
|
2010-04-25 07:45:46 +08:00
|
|
|
}
|
|
|
|
|
2010-04-18 15:40:54 +08:00
|
|
|
/// \brief Make a (potentially elidable) temporary copy of the object
|
|
|
|
/// provided by the given initializer by calling the appropriate copy
|
|
|
|
/// constructor.
|
|
|
|
///
|
|
|
|
/// \param S The Sema object used for type-checking.
|
|
|
|
///
|
2011-01-28 03:55:10 +08:00
|
|
|
/// \param T The type of the temporary object, which must either be
|
2010-04-18 15:40:54 +08:00
|
|
|
/// the type of the initializer expression or a superclass thereof.
|
|
|
|
///
|
|
|
|
/// \param Enter The entity being initialized.
|
|
|
|
///
|
|
|
|
/// \param CurInit The initializer expression.
|
|
|
|
///
|
|
|
|
/// \param IsExtraneousCopy Whether this is an "extraneous" copy that
|
|
|
|
/// is permitted in C++03 (but not C++0x) when binding a reference to
|
|
|
|
/// an rvalue.
|
|
|
|
///
|
|
|
|
/// \returns An expression that copies the initializer expression into
|
|
|
|
/// a temporary object, or an error expression if a copy could not be
|
|
|
|
/// created.
|
2010-08-24 14:29:42 +08:00
|
|
|
static ExprResult CopyObject(Sema &S,
|
2010-09-12 16:07:23 +08:00
|
|
|
QualType T,
|
|
|
|
const InitializedEntity &Entity,
|
|
|
|
ExprResult CurInit,
|
|
|
|
bool IsExtraneousCopy) {
|
2010-04-18 06:01:05 +08:00
|
|
|
// Determine which class type we're copying to.
|
2010-01-24 08:19:41 +08:00
|
|
|
Expr *CurInitExpr = (Expr *)CurInit.get();
|
2011-01-27 15:10:08 +08:00
|
|
|
CXXRecordDecl *Class = 0;
|
2010-04-18 15:40:54 +08:00
|
|
|
if (const RecordType *Record = T->getAs<RecordType>())
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
Class = cast<CXXRecordDecl>(Record->getDecl());
|
|
|
|
if (!Class)
|
|
|
|
return move(CurInit);
|
|
|
|
|
2011-01-22 02:05:27 +08:00
|
|
|
// C++0x [class.copy]p32:
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
// When certain criteria are met, an implementation is allowed to
|
|
|
|
// omit the copy/move construction of a class object, even if the
|
|
|
|
// copy/move constructor and/or destructor for the object have
|
|
|
|
// side effects. [...]
|
|
|
|
// - when a temporary class object that has not been bound to a
|
|
|
|
// reference (12.2) would be copied/moved to a class object
|
|
|
|
// with the same cv-unqualified type, the copy/move operation
|
|
|
|
// can be omitted by constructing the temporary object
|
|
|
|
// directly into the target of the omitted copy/move
|
2011-01-27 15:10:08 +08:00
|
|
|
//
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
// Note that the other three bullets are handled elsewhere. Copy
|
2010-05-15 08:13:29 +08:00
|
|
|
// elision for return statements and throw expressions are handled as part
|
2011-01-27 15:10:08 +08:00
|
|
|
// of constructor initialization, while copy elision for exception handlers
|
2010-05-15 08:13:29 +08:00
|
|
|
// is handled by the run-time.
|
2010-09-15 18:14:12 +08:00
|
|
|
bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class);
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
SourceLocation Loc;
|
|
|
|
switch (Entity.getKind()) {
|
|
|
|
case InitializedEntity::EK_Result:
|
|
|
|
Loc = Entity.getReturnLoc();
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case InitializedEntity::EK_Exception:
|
|
|
|
Loc = Entity.getThrowLoc();
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case InitializedEntity::EK_Variable:
|
2009-12-19 11:01:41 +08:00
|
|
|
Loc = Entity.getDecl()->getLocation();
|
|
|
|
break;
|
|
|
|
|
2010-01-24 08:19:41 +08:00
|
|
|
case InitializedEntity::EK_ArrayElement:
|
|
|
|
case InitializedEntity::EK_Member:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case InitializedEntity::EK_Parameter:
|
|
|
|
case InitializedEntity::EK_Temporary:
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
case InitializedEntity::EK_New:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case InitializedEntity::EK_Base:
|
2011-05-01 15:04:31 +08:00
|
|
|
case InitializedEntity::EK_Delegating:
|
2010-01-23 12:34:47 +08:00
|
|
|
case InitializedEntity::EK_VectorElement:
|
2011-09-20 07:17:44 +08:00
|
|
|
case InitializedEntity::EK_ComplexElement:
|
2010-06-08 00:14:00 +08:00
|
|
|
case InitializedEntity::EK_BlockElement:
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
Loc = CurInitExpr->getLocStart();
|
|
|
|
break;
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
}
|
2010-04-25 05:09:25 +08:00
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
// Make sure that the type we are copying is complete.
|
2010-04-25 05:09:25 +08:00
|
|
|
if (S.RequireCompleteType(Loc, T, S.PDiag(diag::err_temp_copy_incomplete)))
|
|
|
|
return move(CurInit);
|
|
|
|
|
2011-01-22 03:38:21 +08:00
|
|
|
// Perform overload resolution using the class's copy/move constructors.
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
DeclContext::lookup_iterator Con, ConEnd;
|
2010-02-09 07:07:23 +08:00
|
|
|
OverloadCandidateSet CandidateSet(Loc);
|
2010-07-03 07:12:18 +08:00
|
|
|
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
Con != ConEnd; ++Con) {
|
2011-01-22 03:38:21 +08:00
|
|
|
// Only consider copy/move constructors and constructor templates. Per
|
2010-11-12 11:34:06 +08:00
|
|
|
// C++0x [dcl.init]p16, second bullet to class types, this
|
|
|
|
// initialization is direct-initialization.
|
2010-11-09 01:16:59 +08:00
|
|
|
CXXConstructorDecl *Constructor = 0;
|
|
|
|
|
|
|
|
if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) {
|
2011-01-22 03:38:21 +08:00
|
|
|
// Handle copy/moveconstructors, only.
|
2010-11-09 01:16:59 +08:00
|
|
|
if (!Constructor || Constructor->isInvalidDecl() ||
|
2011-01-22 03:38:21 +08:00
|
|
|
!Constructor->isCopyOrMoveConstructor() ||
|
2010-11-12 11:34:06 +08:00
|
|
|
!Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
|
2010-11-09 01:16:59 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
DeclAccessPair FoundDecl
|
|
|
|
= DeclAccessPair::make(Constructor, Constructor->getAccess());
|
|
|
|
S.AddOverloadCandidate(Constructor, FoundDecl,
|
|
|
|
&CurInitExpr, 1, CandidateSet);
|
|
|
|
continue;
|
2011-01-27 15:10:08 +08:00
|
|
|
}
|
2010-11-09 01:16:59 +08:00
|
|
|
|
|
|
|
// Handle constructor templates.
|
|
|
|
FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con);
|
|
|
|
if (ConstructorTmpl->isInvalidDecl())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Constructor = cast<CXXConstructorDecl>(
|
|
|
|
ConstructorTmpl->getTemplatedDecl());
|
2010-11-12 11:34:06 +08:00
|
|
|
if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
continue;
|
2010-03-19 15:35:19 +08:00
|
|
|
|
2010-11-09 01:16:59 +08:00
|
|
|
// FIXME: Do we need to limit this to copy-constructor-like
|
|
|
|
// candidates?
|
2010-03-19 15:35:19 +08:00
|
|
|
DeclAccessPair FoundDecl
|
2010-11-09 01:16:59 +08:00
|
|
|
= DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
|
|
|
|
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0,
|
|
|
|
&CurInitExpr, 1, CandidateSet, true);
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-10-05 15:56:41 +08:00
|
|
|
bool HadMultipleCandidates = (CandidateSet.size() > 1);
|
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
OverloadCandidateSet::iterator Best;
|
2011-02-26 03:41:05 +08:00
|
|
|
switch (CandidateSet.BestViableFunction(S, Loc, Best)) {
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case OR_Success:
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case OR_No_Viable_Function:
|
2010-06-07 23:58:05 +08:00
|
|
|
S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext()
|
|
|
|
? diag::ext_rvalue_to_reference_temp_copy_no_viable
|
|
|
|
: diag::err_temp_copy_no_viable)
|
2009-12-19 11:01:41 +08:00
|
|
|
<< (int)Entity.getKind() << CurInitExpr->getType()
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
<< CurInitExpr->getSourceRange();
|
2010-08-25 04:38:10 +08:00
|
|
|
CandidateSet.NoteCandidates(S, OCD_AllCandidates, &CurInitExpr, 1);
|
2010-06-07 23:58:05 +08:00
|
|
|
if (!IsExtraneousCopy || S.isSFINAEContext())
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2010-06-07 23:58:05 +08:00
|
|
|
return move(CurInit);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case OR_Ambiguous:
|
|
|
|
S.Diag(Loc, diag::err_temp_copy_ambiguous)
|
2009-12-19 11:01:41 +08:00
|
|
|
<< (int)Entity.getKind() << CurInitExpr->getType()
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
<< CurInitExpr->getSourceRange();
|
2010-08-25 04:38:10 +08:00
|
|
|
CandidateSet.NoteCandidates(S, OCD_ViableCandidates, &CurInitExpr, 1);
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case OR_Deleted:
|
|
|
|
S.Diag(Loc, diag::err_temp_copy_deleted)
|
2009-12-19 11:01:41 +08:00
|
|
|
<< (int)Entity.getKind() << CurInitExpr->getType()
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
<< CurInitExpr->getSourceRange();
|
|
|
|
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
|
2011-06-16 07:02:42 +08:00
|
|
|
<< 1 << Best->Function->isDeleted();
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
}
|
|
|
|
|
2010-04-18 06:01:05 +08:00
|
|
|
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
|
2010-08-23 14:44:23 +08:00
|
|
|
ASTOwningVector<Expr*> ConstructorArgs(S);
|
2010-04-18 06:01:05 +08:00
|
|
|
CurInit.release(); // Ownership transferred into MultiExprArg, below.
|
2010-04-18 15:40:54 +08:00
|
|
|
|
2010-04-22 02:47:17 +08:00
|
|
|
S.CheckConstructorAccess(Loc, Constructor, Entity,
|
2010-06-07 23:58:05 +08:00
|
|
|
Best->FoundDecl.getAccess(), IsExtraneousCopy);
|
2010-04-18 15:40:54 +08:00
|
|
|
|
|
|
|
if (IsExtraneousCopy) {
|
|
|
|
// If this is a totally extraneous copy for C++03 reference
|
|
|
|
// binding purposes, just return the original initialization
|
2010-04-18 15:57:34 +08:00
|
|
|
// expression. We don't generate an (elided) copy operation here
|
|
|
|
// because doing so would require us to pass down a flag to avoid
|
|
|
|
// infinite recursion, where each step adds another extraneous,
|
|
|
|
// elidable copy.
|
|
|
|
|
|
|
|
// Instantiate the default arguments of any extra parameters in
|
|
|
|
// the selected copy constructor, as if we were going to create a
|
|
|
|
// proper call to the copy constructor.
|
|
|
|
for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) {
|
|
|
|
ParmVarDecl *Parm = Constructor->getParamDecl(I);
|
|
|
|
if (S.RequireCompleteType(Loc, Parm->getType(),
|
|
|
|
S.PDiag(diag::err_call_incomplete_argument)))
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Build the default argument expression; we don't actually care
|
|
|
|
// if this succeeds or not, because this routine will complain
|
|
|
|
// if there was a problem.
|
|
|
|
S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm);
|
|
|
|
}
|
2010-04-18 15:40:54 +08:00
|
|
|
|
|
|
|
return S.Owned(CurInitExpr);
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-02-26 03:41:05 +08:00
|
|
|
S.MarkDeclarationReferenced(Loc, Constructor);
|
|
|
|
|
2010-04-18 06:01:05 +08:00
|
|
|
// Determine the arguments required to actually perform the
|
2010-04-18 15:40:54 +08:00
|
|
|
// constructor call (we might have derived-to-base conversions, or
|
|
|
|
// the copy constructor may have default arguments).
|
2010-08-27 07:41:50 +08:00
|
|
|
if (S.CompleteConstructorCall(Constructor, MultiExprArg(&CurInitExpr, 1),
|
2010-04-18 06:01:05 +08:00
|
|
|
Loc, ConstructorArgs))
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2010-04-18 06:01:05 +08:00
|
|
|
|
2010-04-25 08:55:24 +08:00
|
|
|
// Actually perform the constructor call.
|
|
|
|
CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
|
2010-08-24 15:32:53 +08:00
|
|
|
move_arg(ConstructorArgs),
|
2011-10-05 15:56:41 +08:00
|
|
|
HadMultipleCandidates,
|
2010-08-24 15:32:53 +08:00
|
|
|
/*ZeroInit*/ false,
|
2010-10-25 16:47:36 +08:00
|
|
|
CXXConstructExpr::CK_Complete,
|
|
|
|
SourceRange());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-25 08:55:24 +08:00
|
|
|
// If we're supposed to bind temporaries, do so.
|
|
|
|
if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity))
|
|
|
|
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
|
|
|
|
return move(CurInit);
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
|
2010-04-22 08:20:18 +08:00
|
|
|
void InitializationSequence::PrintInitLocationNote(Sema &S,
|
|
|
|
const InitializedEntity &Entity) {
|
|
|
|
if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) {
|
|
|
|
if (Entity.getDecl()->getLocation().isInvalid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Entity.getDecl()->getDeclName())
|
|
|
|
S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here)
|
|
|
|
<< Entity.getDecl()->getDeclName();
|
|
|
|
else
|
|
|
|
S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-15 03:07:55 +08:00
|
|
|
static bool isReferenceBinding(const InitializationSequence::Step &s) {
|
|
|
|
return s.Kind == InitializationSequence::SK_BindReference ||
|
|
|
|
s.Kind == InitializationSequence::SK_BindReferenceToTemporary;
|
|
|
|
}
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
ExprResult
|
2009-12-10 07:02:17 +08:00
|
|
|
InitializationSequence::Perform(Sema &S,
|
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
2010-08-27 07:41:50 +08:00
|
|
|
MultiExprArg Args,
|
2009-12-11 01:56:55 +08:00
|
|
|
QualType *ResultType) {
|
2011-06-05 21:59:05 +08:00
|
|
|
if (Failed()) {
|
2009-12-10 07:02:17 +08:00
|
|
|
unsigned NumArgs = Args.size();
|
|
|
|
Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-06-05 21:59:11 +08:00
|
|
|
if (getKind() == DependentSequence) {
|
2009-12-11 01:56:55 +08:00
|
|
|
// If the declaration is a non-dependent, incomplete array type
|
|
|
|
// that has an initializer, then its type will be completed once
|
|
|
|
// the initializer is instantiated.
|
2009-12-22 23:35:07 +08:00
|
|
|
if (ResultType && !Entity.getType()->isDependentType() &&
|
2009-12-11 01:56:55 +08:00
|
|
|
Args.size() == 1) {
|
2009-12-22 23:35:07 +08:00
|
|
|
QualType DeclType = Entity.getType();
|
2009-12-11 01:56:55 +08:00
|
|
|
if (const IncompleteArrayType *ArrayT
|
|
|
|
= S.Context.getAsIncompleteArrayType(DeclType)) {
|
|
|
|
// FIXME: We don't currently have the ability to accurately
|
|
|
|
// compute the length of an initializer list without
|
|
|
|
// performing full type-checking of the initializer list
|
|
|
|
// (since we have to determine where braces are implicitly
|
|
|
|
// introduced and such). So, we fall back to making the array
|
|
|
|
// type a dependently-sized array type with no specified
|
|
|
|
// bound.
|
|
|
|
if (isa<InitListExpr>((Expr *)Args.get()[0])) {
|
|
|
|
SourceRange Brackets;
|
2009-12-22 23:35:07 +08:00
|
|
|
|
2009-12-11 01:56:55 +08:00
|
|
|
// Scavange the location of the brackets from the entity, if we can.
|
2009-12-22 23:35:07 +08:00
|
|
|
if (DeclaratorDecl *DD = Entity.getDecl()) {
|
|
|
|
if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
|
|
|
|
TypeLoc TL = TInfo->getTypeLoc();
|
|
|
|
if (IncompleteArrayTypeLoc *ArrayLoc
|
|
|
|
= dyn_cast<IncompleteArrayTypeLoc>(&TL))
|
|
|
|
Brackets = ArrayLoc->getBracketsRange();
|
|
|
|
}
|
2009-12-11 01:56:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
*ResultType
|
|
|
|
= S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
|
|
|
|
/*NumElts=*/0,
|
|
|
|
ArrayT->getSizeModifier(),
|
|
|
|
ArrayT->getIndexTypeCVRQualifiers(),
|
|
|
|
Brackets);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2011-06-23 04:02:16 +08:00
|
|
|
assert(Kind.getKind() == InitializationKind::IK_Copy ||
|
|
|
|
Kind.isExplicitCast());
|
|
|
|
return ExprResult(Args.release()[0]);
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
|
2011-06-05 21:59:11 +08:00
|
|
|
// No steps means no initialization.
|
|
|
|
if (Steps.empty())
|
2009-12-16 09:38:02 +08:00
|
|
|
return S.Owned((Expr *)0);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-22 23:35:07 +08:00
|
|
|
QualType DestType = Entity.getType().getNonReferenceType();
|
|
|
|
// FIXME: Ugly hack around the fact that Entity.getType() is not
|
2009-12-22 10:10:53 +08:00
|
|
|
// the same as Entity.getDecl()->getType() in cases involving type merging,
|
|
|
|
// and we want latter when it makes sense.
|
2009-12-11 01:56:55 +08:00
|
|
|
if (ResultType)
|
2009-12-22 10:10:53 +08:00
|
|
|
*ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
|
2009-12-22 23:35:07 +08:00
|
|
|
Entity.getType();
|
2009-12-10 07:02:17 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult CurInit = S.Owned((Expr *)0);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// For initialization steps that start with a single initializer,
|
2009-12-16 09:38:02 +08:00
|
|
|
// grab the only argument out the Args and place it into the "current"
|
|
|
|
// initializer.
|
|
|
|
switch (Steps.front().Kind) {
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case SK_ResolveAddressOfOverloadedFunction:
|
|
|
|
case SK_CastDerivedToBaseRValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
case SK_CastDerivedToBaseXValue:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case SK_CastDerivedToBaseLValue:
|
|
|
|
case SK_BindReference:
|
|
|
|
case SK_BindReferenceToTemporary:
|
2010-04-18 15:40:54 +08:00
|
|
|
case SK_ExtraneousCopyToTemporary:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case SK_UserConversion:
|
|
|
|
case SK_QualificationConversionLValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
case SK_QualificationConversionXValue:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case SK_QualificationConversionRValue:
|
|
|
|
case SK_ConversionSequence:
|
2011-09-25 01:47:52 +08:00
|
|
|
case SK_ListConstructorCall:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case SK_ListInitialization:
|
|
|
|
case SK_CAssignment:
|
2009-12-19 16:11:05 +08:00
|
|
|
case SK_StringInit:
|
2011-02-23 02:29:51 +08:00
|
|
|
case SK_ObjCObjectConversion:
|
2011-06-16 07:02:42 +08:00
|
|
|
case SK_ArrayInit:
|
|
|
|
case SK_PassByIndirectCopyRestore:
|
|
|
|
case SK_PassByIndirectRestore:
|
|
|
|
case SK_ProduceObjCObject: {
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
assert(Args.size() == 1);
|
2011-04-09 02:41:53 +08:00
|
|
|
CurInit = Args.get()[0];
|
|
|
|
if (!CurInit.get()) return ExprError();
|
2010-12-04 11:47:34 +08:00
|
|
|
|
|
|
|
// Read from a property when initializing something with it.
|
2011-04-09 02:41:53 +08:00
|
|
|
if (CurInit.get()->getObjectKind() == OK_ObjCProperty) {
|
|
|
|
CurInit = S.ConvertPropertyForRValue(CurInit.take());
|
|
|
|
if (CurInit.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
}
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
break;
|
2010-12-04 11:47:34 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
case SK_ConstructorInitialization:
|
|
|
|
case SK_ZeroInitialization:
|
|
|
|
break;
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// Walk through the computed steps for the initialization sequence,
|
2009-12-10 07:02:17 +08:00
|
|
|
// performing the specified conversions along the way.
|
2009-12-17 02:50:27 +08:00
|
|
|
bool ConstructorInitRequiresZeroInit = false;
|
2009-12-10 07:02:17 +08:00
|
|
|
for (step_iterator Step = step_begin(), StepEnd = step_end();
|
|
|
|
Step != StepEnd; ++Step) {
|
|
|
|
if (CurInit.isInvalid())
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-04-09 02:41:53 +08:00
|
|
|
QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
switch (Step->Kind) {
|
|
|
|
case SK_ResolveAddressOfOverloadedFunction:
|
2011-01-27 15:10:08 +08:00
|
|
|
// Overload resolution determined which function invoke; update the
|
2009-12-10 07:02:17 +08:00
|
|
|
// initializer to reflect that choice.
|
2011-04-09 02:41:53 +08:00
|
|
|
S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl);
|
2010-05-07 02:15:07 +08:00
|
|
|
S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation());
|
2010-02-01 11:16:54 +08:00
|
|
|
CurInit = S.FixOverloadedFunctionReference(move(CurInit),
|
2010-03-31 05:47:33 +08:00
|
|
|
Step->Function.FoundDecl,
|
2010-03-19 15:35:19 +08:00
|
|
|
Step->Function.Function);
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_CastDerivedToBaseRValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
case SK_CastDerivedToBaseXValue:
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_CastDerivedToBaseLValue: {
|
|
|
|
// We have a derived-to-base cast that produces either an rvalue or an
|
|
|
|
// lvalue. Perform that cast.
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXCastPath BasePath;
|
2010-04-25 03:06:50 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Casts to inaccessible base classes are allowed with C-style casts.
|
|
|
|
bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
|
|
|
|
if (S.CheckDerivedToBaseConversion(SourceType, Step->Type,
|
2011-04-09 02:41:53 +08:00
|
|
|
CurInit.get()->getLocStart(),
|
|
|
|
CurInit.get()->getSourceRange(),
|
2010-04-25 03:06:50 +08:00
|
|
|
&BasePath, IgnoreBaseAccess))
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Rework when and how vtables are emitted, by tracking where vtables are
"used" (e.g., we will refer to the vtable in the generated code) and
when they are defined (i.e., because we've seen the key function
definition). Previously, we were effectively tracking "potential
definitions" rather than uses, so we were a bit too eager about emitting
vtables for classes without key functions.
The new scheme:
- For every use of a vtable, Sema calls MarkVTableUsed() to indicate
the use. For example, this occurs when calling a virtual member
function of the class, defining a constructor of that class type,
dynamic_cast'ing from that type to a derived class, casting
to/through a virtual base class, etc.
- For every definition of a vtable, Sema calls MarkVTableUsed() to
indicate the definition. This happens at the end of the translation
unit for classes whose key function has been defined (so we can
delay computation of the key function; see PR6564), and will also
occur with explicit template instantiation definitions.
- For every vtable defined/used, we mark all of the virtual member
functions of that vtable as defined/used, unless we know that the key
function is in another translation unit. This instantiates virtual
member functions when needed.
- At the end of the translation unit, Sema tells CodeGen (via the
ASTConsumer) which vtables must be defined (CodeGen will define
them) and which may be used (for which CodeGen will define the
vtables lazily).
From a language perspective, both the old and the new schemes are
permissible: we're allowed to instantiate virtual member functions
whenever we want per the standard. However, all other C++ compilers
were more lazy than we were, and our eagerness was both a performance
issue (we instantiated too much) and a portability problem (we broke
Boost test cases, which now pass).
Notes:
(1) There's a ton of churn in the tests, because the order in which
vtables get emitted to IR has changed. I've tried to isolate some of
the larger tests from these issues.
(2) Some diagnostics related to
implicitly-instantiated/implicitly-defined virtual member functions
have moved to the point of first use/definition. It's better this
way.
(3) I could use a review of the places where we MarkVTableUsed, to
see if I missed any place where the language effectively requires a
vtable.
Fixes PR7114 and PR6564.
llvm-svn: 103718
2010-05-14 00:44:06 +08:00
|
|
|
if (S.BasePathInvolvesVirtualBase(BasePath)) {
|
|
|
|
QualType T = SourceType;
|
|
|
|
if (const PointerType *Pointer = T->getAs<PointerType>())
|
|
|
|
T = Pointer->getPointeeType();
|
|
|
|
if (const RecordType *RecordTy = T->getAs<RecordType>())
|
2011-04-09 02:41:53 +08:00
|
|
|
S.MarkVTableUsed(CurInit.get()->getLocStart(),
|
Rework when and how vtables are emitted, by tracking where vtables are
"used" (e.g., we will refer to the vtable in the generated code) and
when they are defined (i.e., because we've seen the key function
definition). Previously, we were effectively tracking "potential
definitions" rather than uses, so we were a bit too eager about emitting
vtables for classes without key functions.
The new scheme:
- For every use of a vtable, Sema calls MarkVTableUsed() to indicate
the use. For example, this occurs when calling a virtual member
function of the class, defining a constructor of that class type,
dynamic_cast'ing from that type to a derived class, casting
to/through a virtual base class, etc.
- For every definition of a vtable, Sema calls MarkVTableUsed() to
indicate the definition. This happens at the end of the translation
unit for classes whose key function has been defined (so we can
delay computation of the key function; see PR6564), and will also
occur with explicit template instantiation definitions.
- For every vtable defined/used, we mark all of the virtual member
functions of that vtable as defined/used, unless we know that the key
function is in another translation unit. This instantiates virtual
member functions when needed.
- At the end of the translation unit, Sema tells CodeGen (via the
ASTConsumer) which vtables must be defined (CodeGen will define
them) and which may be used (for which CodeGen will define the
vtables lazily).
From a language perspective, both the old and the new schemes are
permissible: we're allowed to instantiate virtual member functions
whenever we want per the standard. However, all other C++ compilers
were more lazy than we were, and our eagerness was both a performance
issue (we instantiated too much) and a portability problem (we broke
Boost test cases, which now pass).
Notes:
(1) There's a ton of churn in the tests, because the order in which
vtables get emitted to IR has changed. I've tried to isolate some of
the larger tests from these issues.
(2) Some diagnostics related to
implicitly-instantiated/implicitly-defined virtual member functions
have moved to the point of first use/definition. It's better this
way.
(3) I could use a review of the places where we MarkVTableUsed, to
see if I missed any place where the language effectively requires a
vtable.
Fixes PR7114 and PR6564.
llvm-svn: 103718
2010-05-14 00:44:06 +08:00
|
|
|
cast<CXXRecordDecl>(RecordTy->getDecl()));
|
|
|
|
}
|
|
|
|
|
2010-08-25 18:28:54 +08:00
|
|
|
ExprValueKind VK =
|
2010-07-20 12:20:21 +08:00
|
|
|
Step->Kind == SK_CastDerivedToBaseLValue ?
|
2010-08-25 18:28:54 +08:00
|
|
|
VK_LValue :
|
2010-07-20 12:20:21 +08:00
|
|
|
(Step->Kind == SK_CastDerivedToBaseXValue ?
|
2010-08-25 18:28:54 +08:00
|
|
|
VK_XValue :
|
|
|
|
VK_RValue);
|
2010-08-07 14:22:56 +08:00
|
|
|
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
|
|
|
|
Step->Type,
|
2010-08-25 19:45:40 +08:00
|
|
|
CK_DerivedToBase,
|
2010-08-25 18:28:54 +08:00
|
|
|
CurInit.get(),
|
|
|
|
&BasePath, VK));
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_BindReference:
|
2011-04-09 02:41:53 +08:00
|
|
|
if (FieldDecl *BitField = CurInit.get()->getBitField()) {
|
2009-12-10 07:02:17 +08:00
|
|
|
// References cannot bind to bit fields (C++ [dcl.init.ref]p5).
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
|
2009-12-22 23:35:07 +08:00
|
|
|
<< Entity.getType().isVolatileQualified()
|
2009-12-10 07:02:17 +08:00
|
|
|
<< BitField->getDeclName()
|
2011-04-09 02:41:53 +08:00
|
|
|
<< CurInit.get()->getSourceRange();
|
2009-12-10 07:02:17 +08:00
|
|
|
S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2010-01-29 10:47:33 +08:00
|
|
|
|
2011-04-09 02:41:53 +08:00
|
|
|
if (CurInit.get()->refersToVectorElement()) {
|
2010-02-03 03:02:38 +08:00
|
|
|
// References cannot bind to vector elements.
|
2010-02-01 01:18:49 +08:00
|
|
|
S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
|
|
|
|
<< Entity.getType().isVolatileQualified()
|
2011-04-09 02:41:53 +08:00
|
|
|
<< CurInit.get()->getSourceRange();
|
2010-04-22 08:20:18 +08:00
|
|
|
PrintInitLocationNote(S, Entity);
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2010-02-01 01:18:49 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Reference binding does not have any corresponding ASTs.
|
|
|
|
|
|
|
|
// Check exception specifications
|
2011-04-09 02:41:53 +08:00
|
|
|
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2010-02-01 02:34:51 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2010-02-01 02:34:51 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_BindReferenceToTemporary:
|
|
|
|
// Check exception specifications
|
2011-04-09 02:41:53 +08:00
|
|
|
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2009-12-10 07:02:17 +08:00
|
|
|
|
2011-06-22 01:03:29 +08:00
|
|
|
// Materialize the temporary into memory.
|
2011-06-22 23:05:02 +08:00
|
|
|
CurInit = new (S.Context) MaterializeTemporaryExpr(
|
|
|
|
Entity.getType().getNonReferenceType(),
|
|
|
|
CurInit.get(),
|
2011-06-22 01:03:29 +08:00
|
|
|
Entity.getType()->isLValueReferenceType());
|
2011-06-23 00:12:01 +08:00
|
|
|
|
|
|
|
// If we're binding to an Objective-C object that has lifetime, we
|
|
|
|
// need cleanups.
|
|
|
|
if (S.getLangOptions().ObjCAutoRefCount &&
|
|
|
|
CurInit.get()->getType()->isObjCLifetimeType())
|
|
|
|
S.ExprNeedsCleanups = true;
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-18 15:40:54 +08:00
|
|
|
case SK_ExtraneousCopyToTemporary:
|
2011-01-27 15:10:08 +08:00
|
|
|
CurInit = CopyObject(S, Step->Type, Entity, move(CurInit),
|
2010-04-18 15:40:54 +08:00
|
|
|
/*IsExtraneousCopy=*/true);
|
|
|
|
break;
|
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_UserConversion: {
|
|
|
|
// We have a user-defined conversion that invokes either a constructor
|
|
|
|
// or a conversion function.
|
2010-11-15 17:13:47 +08:00
|
|
|
CastKind CastKind;
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
bool IsCopy = false;
|
2010-03-19 15:35:19 +08:00
|
|
|
FunctionDecl *Fn = Step->Function.Function;
|
|
|
|
DeclAccessPair FoundFn = Step->Function.FoundDecl;
|
2011-10-05 15:56:41 +08:00
|
|
|
bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
|
2010-04-25 07:45:46 +08:00
|
|
|
bool CreatedObject = false;
|
2010-02-01 11:16:54 +08:00
|
|
|
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
|
2009-12-10 07:02:17 +08:00
|
|
|
// Build a call to the selected constructor.
|
2010-08-23 14:44:23 +08:00
|
|
|
ASTOwningVector<Expr*> ConstructorArgs(S);
|
2011-04-09 02:41:53 +08:00
|
|
|
SourceLocation Loc = CurInit.get()->getLocStart();
|
2009-12-10 07:02:17 +08:00
|
|
|
CurInit.release(); // Ownership transferred into MultiExprArg, below.
|
2010-02-01 11:16:54 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Determine the arguments required to actually perform the constructor
|
|
|
|
// call.
|
2011-04-09 02:41:53 +08:00
|
|
|
Expr *Arg = CurInit.get();
|
2009-12-10 07:02:17 +08:00
|
|
|
if (S.CompleteConstructorCall(Constructor,
|
2011-04-09 02:41:53 +08:00
|
|
|
MultiExprArg(&Arg, 1),
|
2009-12-10 07:02:17 +08:00
|
|
|
Loc, ConstructorArgs))
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Build the an expression that constructs a temporary.
|
2011-01-27 15:10:08 +08:00
|
|
|
CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
|
2010-08-24 15:32:53 +08:00
|
|
|
move_arg(ConstructorArgs),
|
2011-10-05 15:56:41 +08:00
|
|
|
HadMultipleCandidates,
|
2010-08-24 15:32:53 +08:00
|
|
|
/*ZeroInit*/ false,
|
2010-10-25 16:47:36 +08:00
|
|
|
CXXConstructExpr::CK_Complete,
|
|
|
|
SourceRange());
|
2009-12-10 07:02:17 +08:00
|
|
|
if (CurInit.isInvalid())
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2010-02-01 11:16:54 +08:00
|
|
|
|
2010-04-22 02:47:17 +08:00
|
|
|
S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
|
2010-03-19 15:35:19 +08:00
|
|
|
FoundFn.getAccess());
|
2010-05-07 02:15:07 +08:00
|
|
|
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind = CK_ConstructorConversion;
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
|
|
|
|
if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
|
|
|
|
S.IsDerivedFrom(SourceType, Class))
|
|
|
|
IsCopy = true;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-25 07:45:46 +08:00
|
|
|
CreatedObject = true;
|
2009-12-10 07:02:17 +08:00
|
|
|
} else {
|
|
|
|
// Build a call to the conversion function.
|
2010-02-01 11:16:54 +08:00
|
|
|
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
|
2011-04-09 02:41:53 +08:00
|
|
|
S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0,
|
2010-03-19 15:35:19 +08:00
|
|
|
FoundFn);
|
2010-05-07 02:15:07 +08:00
|
|
|
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
// FIXME: Should we move this initialization into a separate
|
2009-12-10 07:02:17 +08:00
|
|
|
// derived-to-base conversion? I believe the answer is "no", because
|
|
|
|
// we don't want to turn off access control here for c-style casts.
|
2011-04-09 02:41:53 +08:00
|
|
|
ExprResult CurInitExprRes =
|
|
|
|
S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0,
|
|
|
|
FoundFn, Conversion);
|
|
|
|
if(CurInitExprRes.isInvalid())
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2011-04-09 02:41:53 +08:00
|
|
|
CurInit = move(CurInitExprRes);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
// Build the actual call to the conversion function.
|
2011-10-05 15:56:41 +08:00
|
|
|
CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion,
|
|
|
|
HadMultipleCandidates);
|
2009-12-10 07:02:17 +08:00
|
|
|
if (CurInit.isInvalid() || !CurInit.get())
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind = CK_UserDefinedConversion;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-25 07:45:46 +08:00
|
|
|
CreatedObject = Conversion->getResultType()->isRecordType();
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-07-15 03:07:55 +08:00
|
|
|
bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back());
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
if (RequiresCopy || shouldBindAsTemporary(Entity))
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
|
2010-04-25 07:45:46 +08:00
|
|
|
else if (CreatedObject && shouldDestroyTemporary(Entity)) {
|
2011-04-09 02:41:53 +08:00
|
|
|
QualType T = CurInit.get()->getType();
|
2010-04-25 07:45:46 +08:00
|
|
|
if (const RecordType *Record = T->getAs<RecordType>()) {
|
2011-01-27 15:10:08 +08:00
|
|
|
CXXDestructorDecl *Destructor
|
2010-07-02 06:47:18 +08:00
|
|
|
= S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
|
2011-04-09 02:41:53 +08:00
|
|
|
S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor,
|
2010-04-25 07:45:46 +08:00
|
|
|
S.PDiag(diag::err_access_dtor_temp) << T);
|
2011-04-09 02:41:53 +08:00
|
|
|
S.MarkDeclarationReferenced(CurInit.get()->getLocStart(), Destructor);
|
|
|
|
S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart());
|
2010-04-25 07:45:46 +08:00
|
|
|
}
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-08-07 14:22:56 +08:00
|
|
|
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
|
2011-04-09 02:41:53 +08:00
|
|
|
CurInit.get()->getType(),
|
|
|
|
CastKind, CurInit.get(), 0,
|
2011-09-27 09:11:35 +08:00
|
|
|
CurInit.get()->getValueKind()));
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
if (RequiresCopy)
|
2010-04-18 15:40:54 +08:00
|
|
|
CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
|
|
|
|
move(CurInit), /*IsExtraneousCopy=*/false);
|
2010-07-20 12:20:21 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-07-20 12:20:21 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case SK_QualificationConversionLValue:
|
2010-07-20 12:20:21 +08:00
|
|
|
case SK_QualificationConversionXValue:
|
|
|
|
case SK_QualificationConversionRValue: {
|
2009-12-10 07:02:17 +08:00
|
|
|
// Perform a qualification conversion; these can never go wrong.
|
2010-08-25 18:28:54 +08:00
|
|
|
ExprValueKind VK =
|
2010-07-20 12:20:21 +08:00
|
|
|
Step->Kind == SK_QualificationConversionLValue ?
|
2010-08-25 18:28:54 +08:00
|
|
|
VK_LValue :
|
2010-07-20 12:20:21 +08:00
|
|
|
(Step->Kind == SK_QualificationConversionXValue ?
|
2010-08-25 18:28:54 +08:00
|
|
|
VK_XValue :
|
|
|
|
VK_RValue);
|
2011-04-09 02:41:53 +08:00
|
|
|
CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_NoOp, VK);
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2010-07-20 12:20:21 +08:00
|
|
|
}
|
|
|
|
|
2010-04-17 03:30:02 +08:00
|
|
|
case SK_ConversionSequence: {
|
2011-06-16 07:02:42 +08:00
|
|
|
Sema::CheckedConversionKind CCK
|
|
|
|
= Kind.isCStyleCast()? Sema::CCK_CStyleCast
|
|
|
|
: Kind.isFunctionalCast()? Sema::CCK_FunctionalCast
|
|
|
|
: Kind.isExplicitCast()? Sema::CCK_OtherCast
|
|
|
|
: Sema::CCK_ImplicitConversion;
|
2011-04-09 02:41:53 +08:00
|
|
|
ExprResult CurInitExprRes =
|
|
|
|
S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS,
|
2011-06-16 07:02:42 +08:00
|
|
|
getAssignmentAction(Entity), CCK);
|
2011-04-09 02:41:53 +08:00
|
|
|
if (CurInitExprRes.isInvalid())
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2011-04-09 02:41:53 +08:00
|
|
|
CurInit = move(CurInitExprRes);
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2010-04-17 03:30:02 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-11 01:56:55 +08:00
|
|
|
case SK_ListInitialization: {
|
2011-04-09 02:41:53 +08:00
|
|
|
InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
|
2009-12-11 01:56:55 +08:00
|
|
|
QualType Ty = Step->Type;
|
2011-09-25 01:48:00 +08:00
|
|
|
InitListChecker PerformInitList(S, Entity, InitList,
|
|
|
|
ResultType ? *ResultType : Ty, /*VerifyOnly=*/false);
|
|
|
|
if (PerformInitList.HadError())
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2009-12-11 01:56:55 +08:00
|
|
|
|
|
|
|
CurInit.release();
|
2011-09-25 01:48:00 +08:00
|
|
|
CurInit = S.Owned(PerformInitList.getFullyStructuredList());
|
2009-12-11 01:56:55 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-12-15 04:49:26 +08:00
|
|
|
|
2011-09-25 01:47:52 +08:00
|
|
|
case SK_ListConstructorCall:
|
|
|
|
assert(false && "List constructor calls not yet supported.");
|
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
case SK_ConstructorInitialization: {
|
2010-04-17 06:09:46 +08:00
|
|
|
unsigned NumArgs = Args.size();
|
2009-12-15 04:49:26 +08:00
|
|
|
CXXConstructorDecl *Constructor
|
2010-03-19 15:35:19 +08:00
|
|
|
= cast<CXXConstructorDecl>(Step->Function.Function);
|
2011-10-05 15:56:41 +08:00
|
|
|
bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
// Build a call to the selected constructor.
|
2010-08-23 14:44:23 +08:00
|
|
|
ASTOwningVector<Expr*> ConstructorArgs(S);
|
2010-07-22 02:40:47 +08:00
|
|
|
SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
|
|
|
|
? Kind.getEqualLoc()
|
|
|
|
: Kind.getLocation();
|
2010-08-23 15:55:51 +08:00
|
|
|
|
|
|
|
if (Kind.getKind() == InitializationKind::IK_Default) {
|
|
|
|
// Force even a trivial, implicit default constructor to be
|
|
|
|
// semantically checked. We do this explicitly because we don't build
|
|
|
|
// the definition for completely trivial constructors.
|
|
|
|
CXXRecordDecl *ClassDecl = Constructor->getParent();
|
|
|
|
assert(ClassDecl && "No parent class for constructor.");
|
2011-05-12 11:51:51 +08:00
|
|
|
if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
|
2011-05-10 02:22:59 +08:00
|
|
|
ClassDecl->hasTrivialDefaultConstructor() &&
|
|
|
|
!Constructor->isUsed(false))
|
2010-08-23 15:55:51 +08:00
|
|
|
S.DefineImplicitDefaultConstructor(Loc, Constructor);
|
|
|
|
}
|
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
// Determine the arguments required to actually perform the constructor
|
|
|
|
// call.
|
2011-01-27 15:10:08 +08:00
|
|
|
if (S.CompleteConstructorCall(Constructor, move(Args),
|
2009-12-15 04:49:26 +08:00
|
|
|
Loc, ConstructorArgs))
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2011-01-27 15:10:08 +08:00
|
|
|
|
|
|
|
|
2010-03-03 01:18:33 +08:00
|
|
|
if (Entity.getKind() == InitializedEntity::EK_Temporary &&
|
2010-04-17 06:09:46 +08:00
|
|
|
NumArgs != 1 && // FIXME: Hack to work around cast weirdness
|
2010-03-03 01:18:33 +08:00
|
|
|
(Kind.getKind() == InitializationKind::IK_Direct ||
|
|
|
|
Kind.getKind() == InitializationKind::IK_Value)) {
|
|
|
|
// An explicitly-constructed temporary, e.g., X(1, 2).
|
|
|
|
unsigned NumExprs = ConstructorArgs.size();
|
|
|
|
Expr **Exprs = (Expr **)ConstructorArgs.take();
|
2010-07-22 02:31:47 +08:00
|
|
|
S.MarkDeclarationReferenced(Loc, Constructor);
|
2010-10-13 07:32:35 +08:00
|
|
|
S.DiagnoseUseOfDecl(Constructor, Loc);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-09-08 08:15:04 +08:00
|
|
|
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
|
|
|
|
if (!TSInfo)
|
|
|
|
TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-03-03 01:18:33 +08:00
|
|
|
CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
|
|
|
|
Constructor,
|
2010-09-08 08:15:04 +08:00
|
|
|
TSInfo,
|
2011-01-27 15:10:08 +08:00
|
|
|
Exprs,
|
2010-03-03 01:18:33 +08:00
|
|
|
NumExprs,
|
2010-10-25 16:47:36 +08:00
|
|
|
Kind.getParenRange(),
|
2011-10-05 15:56:41 +08:00
|
|
|
HadMultipleCandidates,
|
2010-04-28 04:36:09 +08:00
|
|
|
ConstructorInitRequiresZeroInit));
|
2010-05-03 06:54:08 +08:00
|
|
|
} else {
|
|
|
|
CXXConstructExpr::ConstructionKind ConstructKind =
|
|
|
|
CXXConstructExpr::CK_Complete;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-05-03 06:54:08 +08:00
|
|
|
if (Entity.getKind() == InitializedEntity::EK_Base) {
|
|
|
|
ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
|
2011-01-27 15:10:08 +08:00
|
|
|
CXXConstructExpr::CK_VirtualBase :
|
2010-05-03 06:54:08 +08:00
|
|
|
CXXConstructExpr::CK_NonVirtualBase;
|
2011-05-04 04:19:28 +08:00
|
|
|
} else if (Entity.getKind() == InitializedEntity::EK_Delegating) {
|
2011-05-01 15:04:31 +08:00
|
|
|
ConstructKind = CXXConstructExpr::CK_Delegating;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-10-25 16:47:36 +08:00
|
|
|
// Only get the parenthesis range if it is a direct construction.
|
|
|
|
SourceRange parenRange =
|
|
|
|
Kind.getKind() == InitializationKind::IK_Direct ?
|
|
|
|
Kind.getParenRange() : SourceRange();
|
|
|
|
|
2010-05-15 08:13:29 +08:00
|
|
|
// If the entity allows NRVO, mark the construction as elidable
|
|
|
|
// unconditionally.
|
|
|
|
if (Entity.allowsNRVO())
|
|
|
|
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
|
|
|
|
Constructor, /*Elidable=*/true,
|
|
|
|
move_arg(ConstructorArgs),
|
2011-10-05 15:56:41 +08:00
|
|
|
HadMultipleCandidates,
|
2010-05-15 08:13:29 +08:00
|
|
|
ConstructorInitRequiresZeroInit,
|
2010-10-25 16:47:36 +08:00
|
|
|
ConstructKind,
|
|
|
|
parenRange);
|
2010-05-15 08:13:29 +08:00
|
|
|
else
|
|
|
|
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
|
2011-01-27 15:10:08 +08:00
|
|
|
Constructor,
|
2010-05-15 08:13:29 +08:00
|
|
|
move_arg(ConstructorArgs),
|
2011-10-05 15:56:41 +08:00
|
|
|
HadMultipleCandidates,
|
2010-05-15 08:13:29 +08:00
|
|
|
ConstructorInitRequiresZeroInit,
|
2010-10-25 16:47:36 +08:00
|
|
|
ConstructKind,
|
|
|
|
parenRange);
|
2010-05-03 06:54:08 +08:00
|
|
|
}
|
2009-12-15 04:49:26 +08:00
|
|
|
if (CurInit.isInvalid())
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2010-02-01 11:16:54 +08:00
|
|
|
|
|
|
|
// Only check access if all of that succeeded.
|
2010-04-22 02:47:17 +08:00
|
|
|
S.CheckConstructorAccess(Loc, Constructor, Entity,
|
2010-03-19 15:35:19 +08:00
|
|
|
Step->Function.FoundDecl.getAccess());
|
2010-05-07 02:15:07 +08:00
|
|
|
S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Loc);
|
2011-01-27 15:10:08 +08:00
|
|
|
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
llvm-svn: 100196
2010-04-03 02:24:57 +08:00
|
|
|
if (shouldBindAsTemporary(Entity))
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 08:01:57 +08:00
|
|
|
case SK_ZeroInitialization: {
|
2009-12-17 02:50:27 +08:00
|
|
|
step_iterator NextStep = Step;
|
|
|
|
++NextStep;
|
2011-01-27 15:10:08 +08:00
|
|
|
if (NextStep != StepEnd &&
|
2009-12-17 02:50:27 +08:00
|
|
|
NextStep->Kind == SK_ConstructorInitialization) {
|
|
|
|
// The need for zero-initialization is recorded directly into
|
|
|
|
// the call to the object's constructor within the next step.
|
|
|
|
ConstructorInitRequiresZeroInit = true;
|
|
|
|
} else if (Kind.getKind() == InitializationKind::IK_Value &&
|
|
|
|
S.getLangOptions().CPlusPlus &&
|
|
|
|
!Kind.isImplicitValueInit()) {
|
2010-09-08 08:15:04 +08:00
|
|
|
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
|
|
|
|
if (!TSInfo)
|
2011-01-27 15:10:08 +08:00
|
|
|
TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type,
|
2010-09-08 08:15:04 +08:00
|
|
|
Kind.getRange().getBegin());
|
|
|
|
|
|
|
|
CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr(
|
|
|
|
TSInfo->getType().getNonLValueExprType(S.Context),
|
|
|
|
TSInfo,
|
2009-12-15 08:01:57 +08:00
|
|
|
Kind.getRange().getEnd()));
|
2009-12-17 02:50:27 +08:00
|
|
|
} else {
|
2009-12-15 08:01:57 +08:00
|
|
|
CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
|
2009-12-17 02:50:27 +08:00
|
|
|
}
|
2009-12-15 08:01:57 +08:00
|
|
|
break;
|
|
|
|
}
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
|
|
|
|
case SK_CAssignment: {
|
2011-04-09 02:41:53 +08:00
|
|
|
QualType SourceType = CurInit.get()->getType();
|
|
|
|
ExprResult Result = move(CurInit);
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
Sema::AssignConvertType ConvTy =
|
2011-04-09 02:41:53 +08:00
|
|
|
S.CheckSingleAssignmentConstraints(Step->Type, Result);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
CurInit = move(Result);
|
2009-12-22 15:24:36 +08:00
|
|
|
|
|
|
|
// If this is a call, allow conversion to a transparent union.
|
2011-04-09 02:41:53 +08:00
|
|
|
ExprResult CurInitExprRes = move(CurInit);
|
2009-12-22 15:24:36 +08:00
|
|
|
if (ConvTy != Sema::Compatible &&
|
|
|
|
Entity.getKind() == InitializedEntity::EK_Parameter &&
|
2011-04-09 02:41:53 +08:00
|
|
|
S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes)
|
2009-12-22 15:24:36 +08:00
|
|
|
== Sema::Compatible)
|
|
|
|
ConvTy = Sema::Compatible;
|
2011-04-09 02:41:53 +08:00
|
|
|
if (CurInitExprRes.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
CurInit = move(CurInitExprRes);
|
2009-12-22 15:24:36 +08:00
|
|
|
|
2010-04-22 08:20:18 +08:00
|
|
|
bool Complained;
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
|
|
|
|
Step->Type, SourceType,
|
2011-04-09 02:41:53 +08:00
|
|
|
CurInit.get(),
|
2010-04-22 08:20:18 +08:00
|
|
|
getAssignmentAction(Entity),
|
|
|
|
&Complained)) {
|
|
|
|
PrintInitLocationNote(S, Entity);
|
2010-08-27 07:41:50 +08:00
|
|
|
return ExprError();
|
2010-04-22 08:20:18 +08:00
|
|
|
} else if (Complained)
|
|
|
|
PrintInitLocationNote(S, Entity);
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-12-19 16:11:05 +08:00
|
|
|
|
|
|
|
case SK_StringInit: {
|
|
|
|
QualType Ty = Step->Type;
|
2011-04-09 02:41:53 +08:00
|
|
|
CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty,
|
2011-02-21 15:57:55 +08:00
|
|
|
S.Context.getAsArrayType(Ty), S);
|
2009-12-19 16:11:05 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-08-07 19:51:51 +08:00
|
|
|
|
|
|
|
case SK_ObjCObjectConversion:
|
2011-04-09 02:41:53 +08:00
|
|
|
CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
|
2010-08-25 19:45:40 +08:00
|
|
|
CK_ObjCObjectLValueCast,
|
2011-09-28 05:58:52 +08:00
|
|
|
CurInit.get()->getValueKind());
|
2010-08-07 19:51:51 +08:00
|
|
|
break;
|
2011-02-23 02:29:51 +08:00
|
|
|
|
|
|
|
case SK_ArrayInit:
|
|
|
|
// Okay: we checked everything before creating this step. Note that
|
|
|
|
// this is a GNU extension.
|
|
|
|
S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
|
2011-04-09 02:41:53 +08:00
|
|
|
<< Step->Type << CurInit.get()->getType()
|
|
|
|
<< CurInit.get()->getSourceRange();
|
2011-02-23 02:29:51 +08:00
|
|
|
|
|
|
|
// If the destination type is an incomplete array type, update the
|
|
|
|
// type accordingly.
|
|
|
|
if (ResultType) {
|
|
|
|
if (const IncompleteArrayType *IncompleteDest
|
|
|
|
= S.Context.getAsIncompleteArrayType(Step->Type)) {
|
|
|
|
if (const ConstantArrayType *ConstantSource
|
2011-04-09 02:41:53 +08:00
|
|
|
= S.Context.getAsConstantArrayType(CurInit.get()->getType())) {
|
2011-02-23 02:29:51 +08:00
|
|
|
*ResultType = S.Context.getConstantArrayType(
|
|
|
|
IncompleteDest->getElementType(),
|
|
|
|
ConstantSource->getSize(),
|
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
break;
|
2011-02-23 02:29:51 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
case SK_PassByIndirectCopyRestore:
|
|
|
|
case SK_PassByIndirectRestore:
|
|
|
|
checkIndirectCopyRestoreSource(S, CurInit.get());
|
|
|
|
CurInit = S.Owned(new (S.Context)
|
|
|
|
ObjCIndirectCopyRestoreExpr(CurInit.take(), Step->Type,
|
|
|
|
Step->Kind == SK_PassByIndirectCopyRestore));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SK_ProduceObjCObject:
|
|
|
|
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type,
|
2011-09-10 14:18:15 +08:00
|
|
|
CK_ARCProduceObject,
|
2011-06-16 07:02:42 +08:00
|
|
|
CurInit.take(), 0, VK_RValue));
|
2011-02-23 02:29:51 +08:00
|
|
|
break;
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
}
|
2010-11-11 11:21:53 +08:00
|
|
|
|
|
|
|
// Diagnose non-fatal problems with the completed initialization.
|
|
|
|
if (Entity.getKind() == InitializedEntity::EK_Member &&
|
|
|
|
cast<FieldDecl>(Entity.getDecl())->isBitField())
|
|
|
|
S.CheckBitFieldInitialization(Kind.getLocation(),
|
|
|
|
cast<FieldDecl>(Entity.getDecl()),
|
|
|
|
CurInit.get());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
return move(CurInit);
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Diagnose initialization failures
|
|
|
|
//===----------------------------------------------------------------------===//
|
2011-01-27 15:10:08 +08:00
|
|
|
bool InitializationSequence::Diagnose(Sema &S,
|
2009-12-10 07:02:17 +08:00
|
|
|
const InitializedEntity &Entity,
|
|
|
|
const InitializationKind &Kind,
|
|
|
|
Expr **Args, unsigned NumArgs) {
|
2011-06-05 21:59:05 +08:00
|
|
|
if (!Failed())
|
2009-12-10 07:02:17 +08:00
|
|
|
return false;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-22 23:35:07 +08:00
|
|
|
QualType DestType = Entity.getType();
|
2009-12-10 07:02:17 +08:00
|
|
|
switch (Failure) {
|
|
|
|
case FK_TooManyInitsForReference:
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
// FIXME: Customize for the initialized entity?
|
|
|
|
if (NumArgs == 0)
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_reference_without_init)
|
|
|
|
<< DestType.getNonReferenceType();
|
|
|
|
else // FIXME: diagnostic below could be better!
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
|
|
|
|
<< SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case FK_ArrayNeedsInitList:
|
|
|
|
case FK_ArrayNeedsInitListOrStringLiteral:
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list)
|
|
|
|
<< (Failure == FK_ArrayNeedsInitListOrStringLiteral);
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-02-23 02:29:51 +08:00
|
|
|
case FK_ArrayTypeMismatch:
|
|
|
|
case FK_NonConstantArrayInit:
|
|
|
|
S.Diag(Kind.getLocation(),
|
|
|
|
(Failure == FK_ArrayTypeMismatch
|
|
|
|
? diag::err_array_init_different_type
|
|
|
|
: diag::err_array_init_non_constant_array))
|
|
|
|
<< DestType.getNonReferenceType()
|
|
|
|
<< Args[0]->getType()
|
|
|
|
<< Args[0]->getSourceRange();
|
|
|
|
break;
|
|
|
|
|
2010-03-31 05:47:33 +08:00
|
|
|
case FK_AddressOfOverloadFailed: {
|
|
|
|
DeclAccessPair Found;
|
2011-01-27 15:10:08 +08:00
|
|
|
S.ResolveAddressOfOverloadedFunction(Args[0],
|
2009-12-10 07:02:17 +08:00
|
|
|
DestType.getNonReferenceType(),
|
2010-03-31 05:47:33 +08:00
|
|
|
true,
|
|
|
|
Found);
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2010-03-31 05:47:33 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case FK_ReferenceInitOverloadFailed:
|
2009-12-15 01:27:33 +08:00
|
|
|
case FK_UserConversionOverloadFailed:
|
2009-12-10 07:02:17 +08:00
|
|
|
switch (FailedOverloadResult) {
|
|
|
|
case OR_Ambiguous:
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
if (Failure == FK_UserConversionOverloadFailed)
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
|
|
|
|
<< Args[0]->getType() << DestType
|
|
|
|
<< Args[0]->getSourceRange();
|
|
|
|
else
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
|
|
|
|
<< DestType << Args[0]->getType()
|
|
|
|
<< Args[0]->getSourceRange();
|
|
|
|
|
2010-08-25 04:38:10 +08:00
|
|
|
FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args, NumArgs);
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case OR_No_Viable_Function:
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
|
|
|
|
<< Args[0]->getType() << DestType.getNonReferenceType()
|
|
|
|
<< Args[0]->getSourceRange();
|
2010-08-25 04:38:10 +08:00
|
|
|
FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs);
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case OR_Deleted: {
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
|
|
|
|
<< Args[0]->getType() << DestType.getNonReferenceType()
|
|
|
|
<< Args[0]->getSourceRange();
|
|
|
|
OverloadCandidateSet::iterator Best;
|
2010-08-25 04:38:10 +08:00
|
|
|
OverloadingResult Ovl
|
2010-09-12 16:07:23 +08:00
|
|
|
= FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best,
|
|
|
|
true);
|
2009-12-10 07:02:17 +08:00
|
|
|
if (Ovl == OR_Deleted) {
|
|
|
|
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
|
2011-06-16 07:02:42 +08:00
|
|
|
<< 1 << Best->Function->isDeleted();
|
2009-12-10 07:02:17 +08:00
|
|
|
} else {
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Inconsistent overload resolution?");
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case OR_Success:
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Conversion did not fail!");
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case FK_NonConstLValueReferenceBindingToTemporary:
|
|
|
|
case FK_NonConstLValueReferenceBindingToUnrelated:
|
2011-01-27 15:10:08 +08:00
|
|
|
S.Diag(Kind.getLocation(),
|
2009-12-10 07:02:17 +08:00
|
|
|
Failure == FK_NonConstLValueReferenceBindingToTemporary
|
|
|
|
? diag::err_lvalue_reference_bind_to_temporary
|
|
|
|
: diag::err_lvalue_reference_bind_to_unrelated)
|
2010-01-30 03:39:15 +08:00
|
|
|
<< DestType.getNonReferenceType().isVolatileQualified()
|
2009-12-10 07:02:17 +08:00
|
|
|
<< DestType.getNonReferenceType()
|
|
|
|
<< Args[0]->getType()
|
|
|
|
<< Args[0]->getSourceRange();
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case FK_RValueReferenceBindingToLValue:
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
|
2011-01-21 09:04:33 +08:00
|
|
|
<< DestType.getNonReferenceType() << Args[0]->getType()
|
2009-12-10 07:02:17 +08:00
|
|
|
<< Args[0]->getSourceRange();
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case FK_ReferenceInitDropsQualifiers:
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
|
|
|
|
<< DestType.getNonReferenceType()
|
|
|
|
<< Args[0]->getType()
|
|
|
|
<< Args[0]->getSourceRange();
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-10 07:02:17 +08:00
|
|
|
case FK_ReferenceInitFailed:
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
|
|
|
|
<< DestType.getNonReferenceType()
|
2010-11-24 13:12:34 +08:00
|
|
|
<< Args[0]->isLValue()
|
2009-12-10 07:02:17 +08:00
|
|
|
<< Args[0]->getType()
|
|
|
|
<< Args[0]->getSourceRange();
|
2011-06-11 09:09:30 +08:00
|
|
|
if (DestType.getNonReferenceType()->isObjCObjectPointerType() &&
|
|
|
|
Args[0]->getType()->isObjCObjectPointerType())
|
|
|
|
S.EmitRelatedResultTypeNote(Args[0]);
|
2009-12-10 07:02:17 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-02-20 05:32:49 +08:00
|
|
|
case FK_ConversionFailed: {
|
|
|
|
QualType FromType = Args[0]->getType();
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
|
|
|
|
<< (int)Entity.getKind()
|
2009-12-10 07:02:17 +08:00
|
|
|
<< DestType
|
2010-11-24 13:12:34 +08:00
|
|
|
<< Args[0]->isLValue()
|
2011-02-20 05:32:49 +08:00
|
|
|
<< FromType
|
2009-12-10 07:02:17 +08:00
|
|
|
<< Args[0]->getSourceRange();
|
2011-06-11 09:09:30 +08:00
|
|
|
if (DestType.getNonReferenceType()->isObjCObjectPointerType() &&
|
|
|
|
Args[0]->getType()->isObjCObjectPointerType())
|
|
|
|
S.EmitRelatedResultTypeNote(Args[0]);
|
2009-12-11 01:56:55 +08:00
|
|
|
break;
|
2011-02-20 05:32:49 +08:00
|
|
|
}
|
2011-04-09 02:41:53 +08:00
|
|
|
|
|
|
|
case FK_ConversionFromPropertyFailed:
|
|
|
|
// No-op. This error has already been reported.
|
|
|
|
break;
|
|
|
|
|
2009-12-11 01:56:55 +08:00
|
|
|
case FK_TooManyInitsForScalar: {
|
2009-12-16 09:38:02 +08:00
|
|
|
SourceRange R;
|
|
|
|
|
|
|
|
if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
|
2010-09-09 05:40:08 +08:00
|
|
|
R = SourceRange(InitList->getInit(0)->getLocEnd(),
|
2009-12-16 09:38:02 +08:00
|
|
|
InitList->getLocEnd());
|
2011-01-27 15:10:08 +08:00
|
|
|
else
|
2010-09-09 05:40:08 +08:00
|
|
|
R = SourceRange(Args[0]->getLocEnd(), Args[NumArgs - 1]->getLocEnd());
|
2009-12-11 01:56:55 +08:00
|
|
|
|
2010-09-09 05:40:08 +08:00
|
|
|
R.setBegin(S.PP.getLocForEndOfToken(R.getBegin()));
|
|
|
|
if (Kind.isCStyleOrFunctionalCast())
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
|
|
|
|
<< R;
|
|
|
|
else
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_excess_initializers)
|
|
|
|
<< /*scalar=*/2 << R;
|
2009-12-11 01:56:55 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case FK_ReferenceBindingToInitList:
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
|
|
|
|
<< DestType.getNonReferenceType() << Args[0]->getSourceRange();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FK_InitListBadDestinationType:
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
|
|
|
|
<< (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
case FK_ConstructorOverloadFailed: {
|
|
|
|
SourceRange ArgsRange;
|
|
|
|
if (NumArgs)
|
2011-01-27 15:10:08 +08:00
|
|
|
ArgsRange = SourceRange(Args[0]->getLocStart(),
|
2009-12-15 04:49:26 +08:00
|
|
|
Args[NumArgs - 1]->getLocEnd());
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
// FIXME: Using "DestType" for the entity we're printing is probably
|
|
|
|
// bad.
|
|
|
|
switch (FailedOverloadResult) {
|
|
|
|
case OR_Ambiguous:
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init)
|
|
|
|
<< DestType << ArgsRange;
|
2010-08-25 04:38:10 +08:00
|
|
|
FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates,
|
|
|
|
Args, NumArgs);
|
2009-12-15 04:49:26 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
case OR_No_Viable_Function:
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
if (Kind.getKind() == InitializationKind::IK_Default &&
|
|
|
|
(Entity.getKind() == InitializedEntity::EK_Base ||
|
|
|
|
Entity.getKind() == InitializedEntity::EK_Member) &&
|
|
|
|
isa<CXXConstructorDecl>(S.CurContext)) {
|
|
|
|
// This is implicit default initialization of a member or
|
|
|
|
// base within a constructor. If no viable function was
|
|
|
|
// found, notify the user that she needs to explicitly
|
|
|
|
// initialize this base/member.
|
|
|
|
CXXConstructorDecl *Constructor
|
|
|
|
= cast<CXXConstructorDecl>(S.CurContext);
|
|
|
|
if (Entity.getKind() == InitializedEntity::EK_Base) {
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
|
|
|
|
<< Constructor->isImplicit()
|
|
|
|
<< S.Context.getTypeDeclType(Constructor->getParent())
|
|
|
|
<< /*base=*/0
|
|
|
|
<< Entity.getType();
|
|
|
|
|
|
|
|
RecordDecl *BaseDecl
|
|
|
|
= Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
|
|
|
|
->getDecl();
|
|
|
|
S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
|
|
|
|
<< S.Context.getTagDeclType(BaseDecl);
|
|
|
|
} else {
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
|
|
|
|
<< Constructor->isImplicit()
|
|
|
|
<< S.Context.getTypeDeclType(Constructor->getParent())
|
|
|
|
<< /*member=*/1
|
|
|
|
<< Entity.getName();
|
|
|
|
S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl);
|
|
|
|
|
|
|
|
if (const RecordType *Record
|
|
|
|
= Entity.getType()->getAs<RecordType>())
|
2011-01-27 15:10:08 +08:00
|
|
|
S.Diag(Record->getDecl()->getLocation(),
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
diag::note_previous_decl)
|
|
|
|
<< S.Context.getTagDeclType(Record->getDecl());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
|
|
|
|
<< DestType << ArgsRange;
|
2010-08-25 04:38:10 +08:00
|
|
|
FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs);
|
2009-12-15 04:49:26 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
case OR_Deleted: {
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
|
|
|
|
<< true << DestType << ArgsRange;
|
|
|
|
OverloadCandidateSet::iterator Best;
|
2010-08-25 04:38:10 +08:00
|
|
|
OverloadingResult Ovl
|
|
|
|
= FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
|
2009-12-15 04:49:26 +08:00
|
|
|
if (Ovl == OR_Deleted) {
|
|
|
|
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
|
2011-06-16 07:02:42 +08:00
|
|
|
<< 1 << Best->Function->isDeleted();
|
2009-12-15 04:49:26 +08:00
|
|
|
} else {
|
|
|
|
llvm_unreachable("Inconsistent overload resolution?");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-15 04:49:26 +08:00
|
|
|
case OR_Success:
|
|
|
|
llvm_unreachable("Conversion did not fail!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2009-12-16 09:38:02 +08:00
|
|
|
case FK_DefaultInitOfConst:
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
if (Entity.getKind() == InitializedEntity::EK_Member &&
|
|
|
|
isa<CXXConstructorDecl>(S.CurContext)) {
|
|
|
|
// This is implicit default-initialization of a const member in
|
|
|
|
// a constructor. Complain that it needs to be explicitly
|
|
|
|
// initialized.
|
|
|
|
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
|
|
|
|
<< Constructor->isImplicit()
|
|
|
|
<< S.Context.getTypeDeclType(Constructor->getParent())
|
|
|
|
<< /*const=*/1
|
|
|
|
<< Entity.getName();
|
|
|
|
S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
|
|
|
|
<< Entity.getName();
|
|
|
|
} else {
|
|
|
|
S.Diag(Kind.getLocation(), diag::err_default_init_const)
|
|
|
|
<< DestType << (bool)DestType->getAs<RecordType>();
|
|
|
|
}
|
2009-12-16 09:38:02 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-09-25 01:47:52 +08:00
|
|
|
case FK_Incomplete:
|
|
|
|
S.RequireCompleteType(Kind.getLocation(), DestType,
|
|
|
|
diag::err_init_incomplete_type);
|
|
|
|
break;
|
|
|
|
|
2011-09-25 01:48:00 +08:00
|
|
|
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;
|
|
|
|
}
|
2009-12-10 07:02:17 +08:00
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-22 08:20:18 +08:00
|
|
|
PrintInitLocationNote(S, Entity);
|
2009-12-10 07:02:17 +08:00
|
|
|
return true;
|
|
|
|
}
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
void InitializationSequence::dump(raw_ostream &OS) const {
|
2010-01-30 03:14:02 +08:00
|
|
|
switch (SequenceKind) {
|
|
|
|
case FailedSequence: {
|
|
|
|
OS << "Failed sequence: ";
|
|
|
|
switch (Failure) {
|
|
|
|
case FK_TooManyInitsForReference:
|
|
|
|
OS << "too many initializers for reference";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_ArrayNeedsInitList:
|
|
|
|
OS << "array requires initializer list";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_ArrayNeedsInitListOrStringLiteral:
|
|
|
|
OS << "array requires initializer list or string literal";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-02-23 02:29:51 +08:00
|
|
|
case FK_ArrayTypeMismatch:
|
|
|
|
OS << "array type mismatch";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FK_NonConstantArrayInit:
|
|
|
|
OS << "non-constant array initializer";
|
|
|
|
break;
|
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_AddressOfOverloadFailed:
|
|
|
|
OS << "address of overloaded function failed";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_ReferenceInitOverloadFailed:
|
|
|
|
OS << "overload resolution for reference initialization failed";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_NonConstLValueReferenceBindingToTemporary:
|
|
|
|
OS << "non-const lvalue reference bound to temporary";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_NonConstLValueReferenceBindingToUnrelated:
|
|
|
|
OS << "non-const lvalue reference bound to unrelated type";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_RValueReferenceBindingToLValue:
|
|
|
|
OS << "rvalue reference bound to an lvalue";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_ReferenceInitDropsQualifiers:
|
|
|
|
OS << "reference initialization drops qualifiers";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_ReferenceInitFailed:
|
|
|
|
OS << "reference initialization failed";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_ConversionFailed:
|
|
|
|
OS << "conversion failed";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-04-09 02:41:53 +08:00
|
|
|
case FK_ConversionFromPropertyFailed:
|
|
|
|
OS << "conversion from property failed";
|
|
|
|
break;
|
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_TooManyInitsForScalar:
|
|
|
|
OS << "too many initializers for scalar";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_ReferenceBindingToInitList:
|
|
|
|
OS << "referencing binding to initializer list";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_InitListBadDestinationType:
|
|
|
|
OS << "initializer list for non-aggregate, non-scalar type";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_UserConversionOverloadFailed:
|
|
|
|
OS << "overloading failed for user-defined conversion";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_ConstructorOverloadFailed:
|
|
|
|
OS << "constructor overloading failed";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case FK_DefaultInitOfConst:
|
|
|
|
OS << "default initialization of a const variable";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-05-21 06:12:02 +08:00
|
|
|
case FK_Incomplete:
|
|
|
|
OS << "initialization of incomplete type";
|
|
|
|
break;
|
2011-09-25 01:47:52 +08:00
|
|
|
|
|
|
|
case FK_ListInitializationFailed:
|
2011-09-25 01:48:00 +08:00
|
|
|
OS << "list initialization checker failure";
|
2011-01-27 15:10:08 +08:00
|
|
|
}
|
2010-01-30 03:14:02 +08:00
|
|
|
OS << '\n';
|
|
|
|
return;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case DependentSequence:
|
2011-06-05 21:59:11 +08:00
|
|
|
OS << "Dependent sequence\n";
|
2010-01-30 03:14:02 +08:00
|
|
|
return;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2011-06-05 21:59:11 +08:00
|
|
|
case NormalSequence:
|
|
|
|
OS << "Normal sequence: ";
|
2010-01-30 03:14:02 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
|
|
|
|
if (S != step_begin()) {
|
|
|
|
OS << " -> ";
|
|
|
|
}
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
switch (S->Kind) {
|
|
|
|
case SK_ResolveAddressOfOverloadedFunction:
|
|
|
|
OS << "resolve address of overloaded function";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_CastDerivedToBaseRValue:
|
|
|
|
OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-07-20 12:20:21 +08:00
|
|
|
case SK_CastDerivedToBaseXValue:
|
|
|
|
OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_CastDerivedToBaseLValue:
|
|
|
|
OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_BindReference:
|
|
|
|
OS << "bind reference to lvalue";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_BindReferenceToTemporary:
|
|
|
|
OS << "bind reference to a temporary";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-04-18 15:40:54 +08:00
|
|
|
case SK_ExtraneousCopyToTemporary:
|
|
|
|
OS << "extraneous C++03 copy to temporary";
|
|
|
|
break;
|
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_UserConversion:
|
2010-04-17 17:33:03 +08:00
|
|
|
OS << "user-defined conversion via " << S->Function.Function;
|
2010-01-30 03:14:02 +08:00
|
|
|
break;
|
2010-07-20 12:20:21 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_QualificationConversionRValue:
|
|
|
|
OS << "qualification conversion (rvalue)";
|
|
|
|
|
2010-07-20 12:20:21 +08:00
|
|
|
case SK_QualificationConversionXValue:
|
|
|
|
OS << "qualification conversion (xvalue)";
|
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_QualificationConversionLValue:
|
|
|
|
OS << "qualification conversion (lvalue)";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_ConversionSequence:
|
|
|
|
OS << "implicit conversion sequence (";
|
|
|
|
S->ICS->DebugPrint(); // FIXME: use OS
|
|
|
|
OS << ")";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_ListInitialization:
|
2011-09-25 01:47:52 +08:00
|
|
|
OS << "list aggregate initialization";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SK_ListConstructorCall:
|
|
|
|
OS << "list initialization via constructor";
|
2010-01-30 03:14:02 +08:00
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_ConstructorInitialization:
|
|
|
|
OS << "constructor initialization";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_ZeroInitialization:
|
|
|
|
OS << "zero initialization";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_CAssignment:
|
|
|
|
OS << "C assignment";
|
|
|
|
break;
|
2011-01-27 15:10:08 +08:00
|
|
|
|
2010-01-30 03:14:02 +08:00
|
|
|
case SK_StringInit:
|
|
|
|
OS << "string initialization";
|
|
|
|
break;
|
2010-08-07 19:51:51 +08:00
|
|
|
|
|
|
|
case SK_ObjCObjectConversion:
|
|
|
|
OS << "Objective-C object conversion";
|
|
|
|
break;
|
2011-02-23 02:29:51 +08:00
|
|
|
|
|
|
|
case SK_ArrayInit:
|
|
|
|
OS << "array initialization";
|
|
|
|
break;
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
case SK_PassByIndirectCopyRestore:
|
|
|
|
OS << "pass by indirect copy and restore";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SK_PassByIndirectRestore:
|
|
|
|
OS << "pass by indirect restore";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SK_ProduceObjCObject:
|
|
|
|
OS << "Objective-C object retension";
|
|
|
|
break;
|
2010-01-30 03:14:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitializationSequence::dump() const {
|
|
|
|
dump(llvm::errs());
|
|
|
|
}
|
|
|
|
|
2011-07-27 07:20:30 +08:00
|
|
|
static void DiagnoseNarrowingInInitList(
|
|
|
|
Sema& S, QualType EntityType, const Expr *InitE,
|
|
|
|
bool Constant, const APValue &ConstantValue) {
|
|
|
|
if (Constant) {
|
|
|
|
S.Diag(InitE->getLocStart(),
|
2011-09-18 01:15:52 +08:00
|
|
|
S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt
|
2011-07-27 07:20:30 +08:00
|
|
|
? diag::err_init_list_constant_narrowing
|
|
|
|
: diag::warn_init_list_constant_narrowing)
|
|
|
|
<< InitE->getSourceRange()
|
|
|
|
<< ConstantValue
|
2011-08-29 23:59:37 +08:00
|
|
|
<< EntityType.getLocalUnqualifiedType();
|
2011-07-27 07:20:30 +08:00
|
|
|
} else
|
|
|
|
S.Diag(InitE->getLocStart(),
|
2011-09-18 01:15:52 +08:00
|
|
|
S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt
|
2011-07-27 07:20:30 +08:00
|
|
|
? diag::err_init_list_variable_narrowing
|
|
|
|
: diag::warn_init_list_variable_narrowing)
|
|
|
|
<< InitE->getSourceRange()
|
2011-08-29 23:59:37 +08:00
|
|
|
<< InitE->getType().getLocalUnqualifiedType()
|
|
|
|
<< EntityType.getLocalUnqualifiedType();
|
2011-07-27 07:20:30 +08:00
|
|
|
|
|
|
|
llvm::SmallString<128> StaticCast;
|
|
|
|
llvm::raw_svector_ostream OS(StaticCast);
|
|
|
|
OS << "static_cast<";
|
|
|
|
if (const TypedefType *TT = EntityType->getAs<TypedefType>()) {
|
|
|
|
// It's important to use the typedef's name if there is one so that the
|
|
|
|
// fixit doesn't break code using types like int64_t.
|
|
|
|
//
|
|
|
|
// FIXME: This will break if the typedef requires qualification. But
|
|
|
|
// getQualifiedNameAsString() includes non-machine-parsable components.
|
|
|
|
OS << TT->getDecl();
|
|
|
|
} else if (const BuiltinType *BT = EntityType->getAs<BuiltinType>())
|
|
|
|
OS << BT->getName(S.getLangOptions());
|
|
|
|
else {
|
|
|
|
// Oops, we didn't find the actual type of the variable. Don't emit a fixit
|
|
|
|
// with a broken cast.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
OS << ">(";
|
|
|
|
S.Diag(InitE->getLocStart(), diag::note_init_list_narrowing_override)
|
|
|
|
<< InitE->getSourceRange()
|
|
|
|
<< FixItHint::CreateInsertion(InitE->getLocStart(), OS.str())
|
|
|
|
<< FixItHint::CreateInsertion(
|
|
|
|
S.getPreprocessor().getLocForEndOfToken(InitE->getLocEnd()), ")");
|
|
|
|
}
|
|
|
|
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Initialization helper functions
|
|
|
|
//===----------------------------------------------------------------------===//
|
2011-05-13 06:46:29 +08:00
|
|
|
bool
|
|
|
|
Sema::CanPerformCopyInitialization(const InitializedEntity &Entity,
|
|
|
|
ExprResult Init) {
|
|
|
|
if (Init.isInvalid())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Expr *InitE = Init.get();
|
|
|
|
assert(InitE && "No initialization expression");
|
|
|
|
|
|
|
|
InitializationKind Kind = InitializationKind::CreateCopy(SourceLocation(),
|
|
|
|
SourceLocation());
|
|
|
|
InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
|
2011-06-05 20:23:28 +08:00
|
|
|
return !Seq.Failed();
|
2011-05-13 06:46:29 +08:00
|
|
|
}
|
|
|
|
|
2011-01-27 15:10:08 +08:00
|
|
|
ExprResult
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
Sema::PerformCopyInitialization(const InitializedEntity &Entity,
|
|
|
|
SourceLocation EqualLoc,
|
2011-07-27 07:20:30 +08:00
|
|
|
ExprResult Init,
|
|
|
|
bool TopLevelOfInitList) {
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
if (Init.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
2010-11-11 11:21:53 +08:00
|
|
|
Expr *InitE = Init.get();
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
assert(InitE && "No initialization expression?");
|
|
|
|
|
|
|
|
if (EqualLoc.isInvalid())
|
|
|
|
EqualLoc = InitE->getLocStart();
|
|
|
|
|
|
|
|
InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(),
|
|
|
|
EqualLoc);
|
|
|
|
InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
|
|
|
|
Init.release();
|
2011-07-27 07:20:30 +08:00
|
|
|
|
|
|
|
bool Constant = false;
|
|
|
|
APValue Result;
|
|
|
|
if (TopLevelOfInitList &&
|
|
|
|
Seq.endsWithNarrowing(Context, InitE, &Constant, &Result)) {
|
|
|
|
DiagnoseNarrowingInInitList(*this, Entity.getType(), InitE,
|
|
|
|
Constant, Result);
|
|
|
|
}
|
2010-08-27 07:41:50 +08:00
|
|
|
return Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1));
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
}
|