[cfe-commits] r72233 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/fun-template-def.cpp test/SemaTemplate/instantiate-c99.cpp
Douglas Gregor
dgregor at apple.com
Thu May 21 16:17:50 PDT 2009
Author: dgregor
Date: Thu May 21 18:17:49 2009
New Revision: 72233
URL: http://llvm.org/viewvc/llvm-project?rev=72233&view=rev
Log:
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.
Added:
cfe/trunk/test/SemaTemplate/instantiate-c99.cpp
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
cfe/trunk/test/SemaTemplate/fun-template-def.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=72233&r1=72232&r2=72233&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu May 21 18:17:49 2009
@@ -41,6 +41,7 @@
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 @@
/// (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 @@
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 @@
return SourceRange();
}
+ ImplicitValueInitExpr *Clone(ASTContext &C) const;
+
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=72233&r1=72232&r2=72233&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu May 21 18:17:49 2009
@@ -385,7 +385,9 @@
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 @@
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 @@
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 @@
Expr::Destroy(C);
}
+ImplicitValueInitExpr *ImplicitValueInitExpr::Clone(ASTContext &C) const {
+ return new (C) ImplicitValueInitExpr(getType());
+}
+
//===----------------------------------------------------------------------===//
// ExprIterator.
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=72233&r1=72232&r2=72233&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu May 21 18:17:49 2009
@@ -117,7 +117,8 @@
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 @@
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 @@
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());
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=72233&r1=72232&r2=72233&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Thu May 21 18:17:49 2009
@@ -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 @@
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
@@ -595,6 +596,62 @@
}
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();
Modified: cfe/trunk/test/SemaTemplate/fun-template-def.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/fun-template-def.cpp?rev=72233&r1=72232&r2=72233&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/fun-template-def.cpp (original)
+++ cfe/trunk/test/SemaTemplate/fun-template-def.cpp Thu May 21 18:17:49 2009
@@ -34,9 +34,9 @@
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;
Added: cfe/trunk/test/SemaTemplate/instantiate-c99.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-c99.cpp?rev=72233&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-c99.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-c99.cpp Thu May 21 18:17:49 2009
@@ -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}}
More information about the cfe-commits
mailing list