зеркало из https://github.com/microsoft/clang-1.git
Template instantiation for C99 designated initializers, because we
can. Also, delay semantic analysis of initialization for value-dependent as well as type-dependent expressions, since we can't always properly type-check a value-dependent expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72233 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
ccb97f52af
Коммит
9ea62768fc
|
@ -41,6 +41,7 @@ namespace clang {
|
|||
class Expr : public Stmt {
|
||||
QualType TR;
|
||||
|
||||
protected:
|
||||
/// TypeDependent - Whether this expression is type-dependent
|
||||
/// (C++ [temp.dep.expr]).
|
||||
bool TypeDependent : 1;
|
||||
|
@ -49,7 +50,6 @@ class Expr : public Stmt {
|
|||
/// (C++ [temp.dep.constexpr]).
|
||||
bool ValueDependent : 1;
|
||||
|
||||
protected:
|
||||
// FIXME: Eventually, this constructor should go away and we should
|
||||
// require every subclass to provide type/value-dependence
|
||||
// information.
|
||||
|
@ -2074,7 +2074,8 @@ private:
|
|||
DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
|
||||
const Designator *Designators,
|
||||
SourceLocation EqualOrColonLoc, bool GNUSyntax,
|
||||
unsigned NumSubExprs);
|
||||
Expr **IndexExprs, unsigned NumIndexExprs,
|
||||
Expr *Init);
|
||||
|
||||
explicit DesignatedInitExpr(unsigned NumSubExprs)
|
||||
: Expr(DesignatedInitExprClass, EmptyShell()),
|
||||
|
@ -2337,6 +2338,8 @@ public:
|
|||
return SourceRange();
|
||||
}
|
||||
|
||||
ImplicitValueInitExpr *Clone(ASTContext &C) const;
|
||||
|
||||
// Iterators
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
|
|
|
@ -385,7 +385,9 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
|
|||
InitListExpr::InitListExpr(SourceLocation lbraceloc,
|
||||
Expr **initExprs, unsigned numInits,
|
||||
SourceLocation rbraceloc)
|
||||
: Expr(InitListExprClass, QualType()),
|
||||
: Expr(InitListExprClass, QualType(),
|
||||
hasAnyTypeDependentArguments(initExprs, numInits),
|
||||
hasAnyValueDependentArguments(initExprs, numInits)),
|
||||
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
|
||||
UnionFieldInit(0), HadArrayRangeDesignator(false) {
|
||||
|
||||
|
@ -1632,13 +1634,48 @@ DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
|
|||
const Designator *Designators,
|
||||
SourceLocation EqualOrColonLoc,
|
||||
bool GNUSyntax,
|
||||
unsigned NumSubExprs)
|
||||
: Expr(DesignatedInitExprClass, Ty),
|
||||
Expr **IndexExprs,
|
||||
unsigned NumIndexExprs,
|
||||
Expr *Init)
|
||||
: Expr(DesignatedInitExprClass, Ty,
|
||||
Init->isTypeDependent(), Init->isValueDependent()),
|
||||
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
|
||||
NumDesignators(NumDesignators), NumSubExprs(NumSubExprs) {
|
||||
NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) {
|
||||
this->Designators = new Designator[NumDesignators];
|
||||
for (unsigned I = 0; I != NumDesignators; ++I)
|
||||
|
||||
// Record the initializer itself.
|
||||
child_iterator Child = child_begin();
|
||||
*Child++ = Init;
|
||||
|
||||
// Copy the designators and their subexpressions, computing
|
||||
// value-dependence along the way.
|
||||
unsigned IndexIdx = 0;
|
||||
for (unsigned I = 0; I != NumDesignators; ++I) {
|
||||
this->Designators[I] = Designators[I];
|
||||
|
||||
if (this->Designators[I].isArrayDesignator()) {
|
||||
// Compute type- and value-dependence.
|
||||
Expr *Index = IndexExprs[IndexIdx];
|
||||
ValueDependent = ValueDependent ||
|
||||
Index->isTypeDependent() || Index->isValueDependent();
|
||||
|
||||
// Copy the index expressions into permanent storage.
|
||||
*Child++ = IndexExprs[IndexIdx++];
|
||||
} else if (this->Designators[I].isArrayRangeDesignator()) {
|
||||
// Compute type- and value-dependence.
|
||||
Expr *Start = IndexExprs[IndexIdx];
|
||||
Expr *End = IndexExprs[IndexIdx + 1];
|
||||
ValueDependent = ValueDependent ||
|
||||
Start->isTypeDependent() || Start->isValueDependent() ||
|
||||
End->isTypeDependent() || End->isValueDependent();
|
||||
|
||||
// Copy the start/end expressions into permanent storage.
|
||||
*Child++ = IndexExprs[IndexIdx++];
|
||||
*Child++ = IndexExprs[IndexIdx++];
|
||||
}
|
||||
}
|
||||
|
||||
assert(IndexIdx == NumIndexExprs && "Wrong number of index expressions");
|
||||
}
|
||||
|
||||
DesignatedInitExpr *
|
||||
|
@ -1649,29 +1686,9 @@ DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
|
|||
bool UsesColonSyntax, Expr *Init) {
|
||||
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
|
||||
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
|
||||
DesignatedInitExpr *DIE
|
||||
= new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, Designators,
|
||||
ColonOrEqualLoc, UsesColonSyntax,
|
||||
NumIndexExprs + 1);
|
||||
|
||||
// Fill in the designators
|
||||
unsigned ExpectedNumSubExprs = 0;
|
||||
designators_iterator Desig = DIE->designators_begin();
|
||||
for (unsigned Idx = 0; Idx < NumDesignators; ++Idx, ++Desig) {
|
||||
if (Designators[Idx].isArrayDesignator())
|
||||
++ExpectedNumSubExprs;
|
||||
else if (Designators[Idx].isArrayRangeDesignator())
|
||||
ExpectedNumSubExprs += 2;
|
||||
}
|
||||
assert(ExpectedNumSubExprs == NumIndexExprs && "Wrong number of indices!");
|
||||
|
||||
// Fill in the subexpressions, including the initializer expression.
|
||||
child_iterator Child = DIE->child_begin();
|
||||
*Child++ = Init;
|
||||
for (unsigned Idx = 0; Idx < NumIndexExprs; ++Idx, ++Child)
|
||||
*Child = IndexExprs[Idx];
|
||||
|
||||
return DIE;
|
||||
return new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, Designators,
|
||||
ColonOrEqualLoc, UsesColonSyntax,
|
||||
IndexExprs, NumIndexExprs, Init);
|
||||
}
|
||||
|
||||
DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
|
||||
|
@ -1766,6 +1783,10 @@ void DesignatedInitExpr::Destroy(ASTContext &C) {
|
|||
Expr::Destroy(C);
|
||||
}
|
||||
|
||||
ImplicitValueInitExpr *ImplicitValueInitExpr::Clone(ASTContext &C) const {
|
||||
return new (C) ImplicitValueInitExpr(getType());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ExprIterator.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -117,7 +117,8 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
|
|||
SourceLocation InitLoc,
|
||||
DeclarationName InitEntity,
|
||||
bool DirectInit) {
|
||||
if (DeclType->isDependentType() || Init->isTypeDependent())
|
||||
if (DeclType->isDependentType() ||
|
||||
Init->isTypeDependent() || Init->isValueDependent())
|
||||
return false;
|
||||
|
||||
// C++ [dcl.init.ref]p1:
|
||||
|
@ -1635,7 +1636,9 @@ Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
|
|||
case Designator::ArrayDesignator: {
|
||||
Expr *Index = static_cast<Expr *>(D.getArrayIndex());
|
||||
llvm::APSInt IndexValue;
|
||||
if (CheckArrayDesignatorExpr(*this, Index, IndexValue))
|
||||
if (!Index->isTypeDependent() &&
|
||||
!Index->isValueDependent() &&
|
||||
CheckArrayDesignatorExpr(*this, Index, IndexValue))
|
||||
Invalid = true;
|
||||
else {
|
||||
Designators.push_back(ASTDesignator(InitExpressions.size(),
|
||||
|
@ -1651,12 +1654,20 @@ Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
|
|||
Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd());
|
||||
llvm::APSInt StartValue;
|
||||
llvm::APSInt EndValue;
|
||||
if (CheckArrayDesignatorExpr(*this, StartIndex, StartValue) ||
|
||||
CheckArrayDesignatorExpr(*this, EndIndex, EndValue))
|
||||
bool StartDependent = StartIndex->isTypeDependent() ||
|
||||
StartIndex->isValueDependent();
|
||||
bool EndDependent = EndIndex->isTypeDependent() ||
|
||||
EndIndex->isValueDependent();
|
||||
if ((!StartDependent &&
|
||||
CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) ||
|
||||
(!EndDependent &&
|
||||
CheckArrayDesignatorExpr(*this, EndIndex, EndValue)))
|
||||
Invalid = true;
|
||||
else {
|
||||
// Make sure we're comparing values with the same bit width.
|
||||
if (StartValue.getBitWidth() > EndValue.getBitWidth())
|
||||
if (StartDependent || EndDependent) {
|
||||
// Nothing to compute.
|
||||
} else if (StartValue.getBitWidth() > EndValue.getBitWidth())
|
||||
EndValue.extend(StartValue.getBitWidth());
|
||||
else if (StartValue.getBitWidth() < EndValue.getBitWidth())
|
||||
StartValue.extend(EndValue.getBitWidth());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/Parse/DeclSpec.h"
|
||||
#include "clang/Parse/Designator.h"
|
||||
#include "clang/Lex/Preprocessor.h" // for the identifier table
|
||||
#include "llvm/Support/Compiler.h"
|
||||
using namespace clang;
|
||||
|
@ -61,8 +62,8 @@ namespace {
|
|||
OwningExprResult VisitChooseExpr(ChooseExpr *E);
|
||||
OwningExprResult VisitVAArgExpr(VAArgExpr *E);
|
||||
OwningExprResult VisitInitListExpr(InitListExpr *E);
|
||||
// FIXME: DesignatedInitExpr
|
||||
// FIXME: ImplicitValueInitExpr
|
||||
OwningExprResult VisitDesignatedInitExpr(DesignatedInitExpr *E);
|
||||
OwningExprResult VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
|
||||
// FIXME: ExtVectorElementExpr
|
||||
// FIXME: BlockExpr
|
||||
// FIXME: BlockDeclRefExpr
|
||||
|
@ -594,6 +595,62 @@ TemplateExprInstantiator::VisitInitListExpr(InitListExpr *E) {
|
|||
E->getRBraceLoc());
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
|
||||
Designation Desig;
|
||||
|
||||
// Instantiate the initializer value
|
||||
OwningExprResult Init = Visit(E->getInit());
|
||||
if (Init.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
// Instantiate the designators.
|
||||
ExprVector ArrayExprs(SemaRef); // Expresses used in array designators
|
||||
for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
|
||||
DEnd = E->designators_end();
|
||||
D != DEnd; ++D) {
|
||||
if (D->isFieldDesignator()) {
|
||||
Desig.AddDesignator(Designator::getField(D->getFieldName(),
|
||||
D->getDotLoc(),
|
||||
D->getFieldLoc()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (D->isArrayDesignator()) {
|
||||
OwningExprResult Index = Visit(E->getArrayIndex(*D));
|
||||
if (Index.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
Desig.AddDesignator(Designator::getArray(Index.get(),
|
||||
D->getLBracketLoc()));
|
||||
|
||||
ArrayExprs.push_back(Index.release());
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(false && "No array range designators, yet");
|
||||
}
|
||||
|
||||
OwningExprResult Result =
|
||||
SemaRef.ActOnDesignatedInitializer(Desig,
|
||||
E->getEqualOrColonLoc(),
|
||||
E->usesGNUSyntax(),
|
||||
move(Init));
|
||||
if (Result.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
ArrayExprs.take();
|
||||
return move(Result);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitImplicitValueInitExpr(
|
||||
ImplicitValueInitExpr *E) {
|
||||
assert(!E->isTypeDependent() && !E->isValueDependent() &&
|
||||
"ImplicitValueInitExprs are never dependent");
|
||||
return SemaRef.Clone(E);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
|
||||
bool isSizeOf = E->isSizeOf();
|
||||
|
|
|
@ -34,9 +34,9 @@ T f(T t1, U u1, int i1)
|
|||
new (t1, u1) int;
|
||||
delete t1;
|
||||
|
||||
dummy d1 = sizeof(t1); // expected-error {{cannot initialize 'd1'}}
|
||||
dummy d1 = sizeof(t1); // FIXME: delayed checking okay?
|
||||
dummy d2 = offsetof(T, foo); // expected-error {{cannot initialize 'd2'}}
|
||||
dummy d3 = __alignof(u1); // expected-error {{cannot initialize 'd3'}}
|
||||
dummy d3 = __alignof(u1); // FIXME: delayed checking okay?
|
||||
i1 = typeid(t1); // expected-error {{incompatible type assigning}}
|
||||
|
||||
return u1;
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
// Test template instantiation for C99-specific features.
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Designated initializers
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T, typename XType, typename YType>
|
||||
struct DesigInit0 {
|
||||
void f(XType x, YType y) {
|
||||
T agg = {
|
||||
.y = y, // expected-error{{does not refer}}
|
||||
.x = x // expected-error{{does not refer}}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct Point2D {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
template struct DesigInit0<Point2D, int, double>;
|
||||
|
||||
struct Point3D {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
template struct DesigInit0<Point3D, int, double>;
|
||||
|
||||
struct Color {
|
||||
unsigned char red, green, blue;
|
||||
};
|
||||
|
||||
struct ColorPoint3D {
|
||||
Color color;
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
template struct DesigInit0<ColorPoint3D, int, double>;
|
||||
template struct DesigInit0<Color, int, double>; // expected-note{{instantiation}}
|
||||
|
||||
template<typename T, int Subscript1, int Subscript2,
|
||||
typename Val1, typename Val2>
|
||||
struct DesigArrayInit0 {
|
||||
void f(Val1 val1, Val2 val2) {
|
||||
T array = {
|
||||
[Subscript1] = val1,
|
||||
[Subscript2] = val2 // expected-error{{exceeds array bounds}}
|
||||
};
|
||||
|
||||
int array2[10] = { [5] = 3 };
|
||||
}
|
||||
};
|
||||
|
||||
template struct DesigArrayInit0<int[8], 5, 3, float, int>;
|
||||
template struct DesigArrayInit0<int[8], 5, 13, float, int>; // expected-note{{instantiation}}
|
Загрузка…
Ссылка в новой задаче