forked from OSchip/llvm-project
Straw man for instantiation of expressions. Use it to instantiate the
width of bitfields. I'll be burning this down and replacing it with a properly-dispatched implementation like the one used for types. llvm-svn: 66796
This commit is contained in:
parent
f16a991262
commit
573c7467df
|
@ -1805,6 +1805,11 @@ public:
|
|||
QualType InstantiateType(QualType T, const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation Loc, DeclarationName Entity);
|
||||
|
||||
OwningExprResult InstantiateExpr(Expr *E,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs);
|
||||
|
||||
bool
|
||||
InstantiateBaseSpecifiers(ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
||||
ClassTemplateDecl *ClassTemplate);
|
||||
|
@ -2305,7 +2310,7 @@ struct BlockSemaInfo {
|
|||
template <typename T>
|
||||
class ExprOwningPtr : public Action::ExprArg {
|
||||
public:
|
||||
ExprOwningPtr(Sema *S, T *expr) : Action::ExprArg(*S, expr) {};
|
||||
ExprOwningPtr(Sema *S, T *expr) : Action::ExprArg(*S, expr) {}
|
||||
|
||||
void reset(T* p) { Action::ExprArg::operator=(p); }
|
||||
T* get() const { return static_cast<T*>(Action::ExprArg::get()); }
|
||||
|
|
|
@ -550,6 +550,50 @@ QualType Sema::InstantiateType(QualType T,
|
|||
return Instantiator(T);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===/
|
||||
// Template Instantiation for Expressions
|
||||
//===----------------------------------------------------------------------===/
|
||||
Sema::OwningExprResult
|
||||
Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
|
||||
unsigned NumTemplateArgs) {
|
||||
if (IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E))
|
||||
return Owned(new (Context) IntegerLiteral(IL->getValue(), IL->getType(),
|
||||
IL->getSourceRange().getBegin()));
|
||||
else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
|
||||
Decl *D = DRE->getDecl();
|
||||
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
||||
assert(NTTP->getDepth() == 0 && "No nested templates yet");
|
||||
QualType T = NTTP->getType();
|
||||
if (T->isDependentType()) {
|
||||
// FIXME: We'll be doing this instantiation a lot. Should we
|
||||
// cache this information in the TemplateArgument itself?
|
||||
T = InstantiateType(T, TemplateArgs, NumTemplateArgs,
|
||||
E->getSourceRange().getBegin(),
|
||||
NTTP->getDeclName());
|
||||
if (T.isNull())
|
||||
return ExprError();
|
||||
}
|
||||
return Owned(new (Context) IntegerLiteral(
|
||||
*TemplateArgs[NTTP->getPosition()].getAsIntegral(),
|
||||
T, E->getSourceRange().getBegin()));
|
||||
} else
|
||||
assert(false && "Yes, this is lame");
|
||||
} else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
|
||||
OwningExprResult SubExpr
|
||||
= InstantiateExpr(PE->getSubExpr(), TemplateArgs,
|
||||
NumTemplateArgs);
|
||||
if (SubExpr.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
return Owned(new (Context) ParenExpr(E->getSourceRange().getBegin(),
|
||||
E->getSourceRange().getEnd(),
|
||||
(Expr *)SubExpr.release()));
|
||||
} else
|
||||
assert(false && "Yes, this is lame");
|
||||
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
/// \brief Instantiate the base class specifiers of the given class
|
||||
/// template specialization.
|
||||
///
|
||||
|
@ -694,6 +738,7 @@ Sema::InstantiateClassTemplateSpecialization(
|
|||
else if (FieldDecl *Field = dyn_cast<FieldDecl>(*Member)) {
|
||||
// FIXME: Simplified instantiation of fields needs to be made
|
||||
// "real".
|
||||
bool InvalidDecl = false;
|
||||
QualType T = Field->getType();
|
||||
if (T->isDependentType()) {
|
||||
T = InstantiateType(T, ClassTemplateSpec->getTemplateArgs(),
|
||||
|
@ -710,20 +755,40 @@ Sema::InstantiateClassTemplateSpecialization(
|
|||
Diag(Field->getLocation(), diag::err_field_instantiates_to_function)
|
||||
<< T;
|
||||
T = QualType();
|
||||
InvalidDecl = true;
|
||||
}
|
||||
}
|
||||
|
||||
Expr *BitWidth = Field->getBitWidth();
|
||||
if (InvalidDecl)
|
||||
BitWidth = 0;
|
||||
if (BitWidth &&
|
||||
(BitWidth->isTypeDependent() || BitWidth->isValueDependent())) {
|
||||
OwningExprResult InstantiatedBitWidth
|
||||
= InstantiateExpr(BitWidth,
|
||||
ClassTemplateSpec->getTemplateArgs(),
|
||||
ClassTemplateSpec->getNumTemplateArgs());
|
||||
if (InstantiatedBitWidth.isInvalid()) {
|
||||
Invalid = InvalidDecl = true;
|
||||
BitWidth = 0;
|
||||
} else
|
||||
BitWidth = (Expr *)InstantiatedBitWidth.release();
|
||||
}
|
||||
|
||||
FieldDecl *New = CheckFieldDecl(Field->getDeclName(), T,
|
||||
ClassTemplateSpec,
|
||||
Field->getLocation(),
|
||||
Field->isMutable(),
|
||||
Field->getBitWidth(),
|
||||
BitWidth,
|
||||
Field->getAccess(),
|
||||
0);
|
||||
if (New) {
|
||||
ClassTemplateSpec->addDecl(New);
|
||||
Fields.push_back(New);
|
||||
|
||||
if (InvalidDecl)
|
||||
New->setInvalidDecl();
|
||||
|
||||
if (New->isInvalidDecl())
|
||||
Invalid = true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
template<int I, int J>
|
||||
struct Bitfields {
|
||||
int simple : I; // expected-error{{bit-field 'simple' has zero width}}
|
||||
int parens : (J);
|
||||
};
|
||||
|
||||
void test_Bitfields(Bitfields<0, 5> *b) {
|
||||
(void)sizeof(Bitfields<10, 5>);
|
||||
(void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'struct Bitfields<0, 1>' requested here}}
|
||||
}
|
Loading…
Reference in New Issue