Implement template instantiation for several more kinds of expressions:
- C++ function casts, e.g., T(foo) - sizeof(), alignof() More importantly, this allows us to verify that we're performing overload resolution during template instantiation, with argument-dependent lookup and the "cached" results of name lookup from the template definition. llvm-svn: 66947
This commit is contained in:
parent
5b86bf527e
commit
0950e41b73
|
@ -2553,8 +2553,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
|
||||||
FT->getResultType(), SourceLocation());
|
FT->getResultType(), SourceLocation());
|
||||||
|
|
||||||
// Build sizeof(returnType)
|
// Build sizeof(returnType)
|
||||||
SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true, true,
|
SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
|
||||||
returnType.getAsOpaquePtr(),
|
returnType,
|
||||||
Context->getSizeType(),
|
Context->getSizeType(),
|
||||||
SourceLocation(), SourceLocation());
|
SourceLocation(), SourceLocation());
|
||||||
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
|
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
|
||||||
|
|
|
@ -692,20 +692,26 @@ class SizeOfAlignOfExpr : public Expr {
|
||||||
} Argument;
|
} Argument;
|
||||||
SourceLocation OpLoc, RParenLoc;
|
SourceLocation OpLoc, RParenLoc;
|
||||||
public:
|
public:
|
||||||
SizeOfAlignOfExpr(bool issizeof, bool istype, void *argument,
|
SizeOfAlignOfExpr(bool issizeof, QualType T,
|
||||||
QualType resultType, SourceLocation op,
|
QualType resultType, SourceLocation op,
|
||||||
SourceLocation rp) :
|
SourceLocation rp) :
|
||||||
Expr(SizeOfAlignOfExprClass, resultType,
|
Expr(SizeOfAlignOfExprClass, resultType,
|
||||||
false, // Never type-dependent.
|
false, // Never type-dependent (C++ [temp.dep.expr]p3).
|
||||||
// Value-dependent if the argument is type-dependent.
|
// Value-dependent if the argument is type-dependent.
|
||||||
(istype ? QualType::getFromOpaquePtr(argument)->isDependentType()
|
T->isDependentType()),
|
||||||
: static_cast<Expr*>(argument)->isTypeDependent())),
|
isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
|
||||||
isSizeof(issizeof), isType(istype), OpLoc(op), RParenLoc(rp) {
|
Argument.Ty = T.getAsOpaquePtr();
|
||||||
if (isType)
|
}
|
||||||
Argument.Ty = argument;
|
|
||||||
else
|
SizeOfAlignOfExpr(bool issizeof, Expr *E,
|
||||||
// argument was an Expr*, so cast it back to that to be safe
|
QualType resultType, SourceLocation op,
|
||||||
Argument.Ex = static_cast<Expr*>(argument);
|
SourceLocation rp) :
|
||||||
|
Expr(SizeOfAlignOfExprClass, resultType,
|
||||||
|
false, // Never type-dependent (C++ [temp.dep.expr]p3).
|
||||||
|
// Value-dependent if the argument is type-dependent.
|
||||||
|
E->isTypeDependent()),
|
||||||
|
isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) {
|
||||||
|
Argument.Ex = E;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Destroy(ASTContext& C);
|
virtual void Destroy(ASTContext& C);
|
||||||
|
|
|
@ -467,6 +467,8 @@ public:
|
||||||
const_arg_iterator arg_begin() const { return Args; }
|
const_arg_iterator arg_begin() const { return Args; }
|
||||||
const_arg_iterator arg_end() const { return Args + NumArgs; }
|
const_arg_iterator arg_end() const { return Args + NumArgs; }
|
||||||
|
|
||||||
|
unsigned getNumArgs() const { return NumArgs; }
|
||||||
|
|
||||||
virtual SourceRange getSourceRange() const {
|
virtual SourceRange getSourceRange() const {
|
||||||
return SourceRange(TyBeginLoc, RParenLoc);
|
return SourceRange(TyBeginLoc, RParenLoc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,10 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(CXXConstructorDecl *Cons,
|
||||||
Expr **Args,
|
Expr **Args,
|
||||||
unsigned NumArgs,
|
unsigned NumArgs,
|
||||||
SourceLocation rParenLoc)
|
SourceLocation rParenLoc)
|
||||||
: Expr(CXXTemporaryObjectExprClass, writtenTy),
|
: Expr(CXXTemporaryObjectExprClass, writtenTy,
|
||||||
|
writtenTy->isDependentType(),
|
||||||
|
(writtenTy->isDependentType() ||
|
||||||
|
CallExpr::hasAnyValueDependentArguments(Args, NumArgs))),
|
||||||
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc),
|
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc),
|
||||||
Constructor(Cons), Args(0), NumArgs(NumArgs) {
|
Constructor(Cons), Args(0), NumArgs(NumArgs) {
|
||||||
if (NumArgs > 0) {
|
if (NumArgs > 0) {
|
||||||
|
|
|
@ -832,9 +832,14 @@ SizeOfAlignOfExpr::CreateImpl(Deserializer& D, ASTContext& C) {
|
||||||
QualType Res = QualType::ReadVal(D);
|
QualType Res = QualType::ReadVal(D);
|
||||||
SourceLocation OpLoc = SourceLocation::ReadVal(D);
|
SourceLocation OpLoc = SourceLocation::ReadVal(D);
|
||||||
SourceLocation RParenLoc = SourceLocation::ReadVal(D);
|
SourceLocation RParenLoc = SourceLocation::ReadVal(D);
|
||||||
|
|
||||||
return new SizeOfAlignOfExpr(isSizeof, isType, Argument, Res,
|
if (isType)
|
||||||
OpLoc, RParenLoc);
|
return new (C) SizeOfAlignOfExpr(isSizeof,
|
||||||
|
QualType::getFromOpaquePtr(Argument),
|
||||||
|
Res, OpLoc, RParenLoc);
|
||||||
|
|
||||||
|
return new (C) SizeOfAlignOfExpr(isSizeof, (Expr *)Argument,
|
||||||
|
Res, OpLoc, RParenLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StmtExpr::EmitImpl(Serializer& S) const {
|
void StmtExpr::EmitImpl(Serializer& S) const {
|
||||||
|
|
|
@ -967,9 +967,12 @@ ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
|
void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
|
||||||
for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
|
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
|
||||||
if (Expr *E = getArg(Arg).getAsExpr())
|
// FIXME: Not all expressions get cloned, so we can't yet perform
|
||||||
E->Destroy(C);
|
// this destruction.
|
||||||
|
// if (Expr *E = getArg(Arg).getAsExpr())
|
||||||
|
// E->Destroy(C);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassTemplateSpecializationType::iterator
|
ClassTemplateSpecializationType::iterator
|
||||||
|
|
|
@ -1188,6 +1188,11 @@ public:
|
||||||
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
|
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
|
||||||
void *TyOrEx, const SourceRange &ArgRange);
|
void *TyOrEx, const SourceRange &ArgRange);
|
||||||
|
|
||||||
|
OwningExprResult CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc,
|
||||||
|
bool isSizeOf, SourceRange R);
|
||||||
|
OwningExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
|
||||||
|
bool isSizeOf, SourceRange R);
|
||||||
|
|
||||||
bool CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &R);
|
bool CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &R);
|
||||||
bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
|
bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
|
||||||
const SourceRange &R, bool isSizeof);
|
const SourceRange &R, bool isSizeof);
|
||||||
|
|
|
@ -1220,6 +1220,50 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc,
|
||||||
return CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
|
return CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Build a sizeof or alignof expression given a type operand.
|
||||||
|
Action::OwningExprResult
|
||||||
|
Sema::CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc,
|
||||||
|
bool isSizeOf, SourceRange R) {
|
||||||
|
if (T.isNull())
|
||||||
|
return ExprError();
|
||||||
|
|
||||||
|
if (!T->isDependentType() &&
|
||||||
|
CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf))
|
||||||
|
return ExprError();
|
||||||
|
|
||||||
|
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
|
||||||
|
return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, T,
|
||||||
|
Context.getSizeType(), OpLoc,
|
||||||
|
R.getEnd()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Build a sizeof or alignof expression given an expression
|
||||||
|
/// operand.
|
||||||
|
Action::OwningExprResult
|
||||||
|
Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
|
||||||
|
bool isSizeOf, SourceRange R) {
|
||||||
|
// Verify that the operand is valid.
|
||||||
|
bool isInvalid = false;
|
||||||
|
if (E->isTypeDependent()) {
|
||||||
|
// Delay type-checking for type-dependent expressions.
|
||||||
|
} else if (!isSizeOf) {
|
||||||
|
isInvalid = CheckAlignOfExpr(E, OpLoc, R);
|
||||||
|
} else if (E->isBitField()) { // C99 6.5.3.4p1.
|
||||||
|
Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
|
||||||
|
isInvalid = true;
|
||||||
|
} else {
|
||||||
|
isInvalid = CheckSizeOfAlignOfOperand(E->getType(), OpLoc, R, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInvalid)
|
||||||
|
return ExprError();
|
||||||
|
|
||||||
|
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
|
||||||
|
return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, E,
|
||||||
|
Context.getSizeType(), OpLoc,
|
||||||
|
R.getEnd()));
|
||||||
|
}
|
||||||
|
|
||||||
/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
|
/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
|
||||||
/// the same for @c alignof and @c __alignof
|
/// the same for @c alignof and @c __alignof
|
||||||
/// Note that the ArgRange is invalid if isType is false.
|
/// Note that the ArgRange is invalid if isType is false.
|
||||||
|
@ -1229,42 +1273,20 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
|
||||||
// If error parsing type, ignore.
|
// If error parsing type, ignore.
|
||||||
if (TyOrEx == 0) return ExprError();
|
if (TyOrEx == 0) return ExprError();
|
||||||
|
|
||||||
QualType ArgTy;
|
|
||||||
SourceRange Range;
|
|
||||||
if (isType) {
|
if (isType) {
|
||||||
ArgTy = QualType::getFromOpaquePtr(TyOrEx);
|
QualType ArgTy = QualType::getFromOpaquePtr(TyOrEx);
|
||||||
Range = ArgRange;
|
return CreateSizeOfAlignOfExpr(ArgTy, OpLoc, isSizeof, ArgRange);
|
||||||
|
}
|
||||||
// Verify that the operand is valid.
|
|
||||||
if (CheckSizeOfAlignOfOperand(ArgTy, OpLoc, Range, isSizeof))
|
|
||||||
return ExprError();
|
|
||||||
} else {
|
|
||||||
// Get the end location.
|
|
||||||
Expr *ArgEx = (Expr *)TyOrEx;
|
|
||||||
Range = ArgEx->getSourceRange();
|
|
||||||
ArgTy = ArgEx->getType();
|
|
||||||
|
|
||||||
// Verify that the operand is valid.
|
|
||||||
bool isInvalid;
|
|
||||||
if (!isSizeof) {
|
|
||||||
isInvalid = CheckAlignOfExpr(ArgEx, OpLoc, Range);
|
|
||||||
} else if (ArgEx->isBitField()) { // C99 6.5.3.4p1.
|
|
||||||
Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
|
|
||||||
isInvalid = true;
|
|
||||||
} else {
|
|
||||||
isInvalid = CheckSizeOfAlignOfOperand(ArgTy, OpLoc, Range, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInvalid) {
|
|
||||||
DeleteExpr(ArgEx);
|
|
||||||
return ExprError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
|
// Get the end location.
|
||||||
return Owned(new (Context) SizeOfAlignOfExpr(isSizeof, isType, TyOrEx,
|
Expr *ArgEx = (Expr *)TyOrEx;
|
||||||
Context.getSizeType(), OpLoc,
|
Action::OwningExprResult Result
|
||||||
Range.getEnd()));
|
= CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
|
||||||
|
|
||||||
|
if (Result.isInvalid())
|
||||||
|
DeleteExpr(ArgEx);
|
||||||
|
|
||||||
|
return move(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) {
|
QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) {
|
||||||
|
|
|
@ -122,6 +122,13 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
|
||||||
SourceLocation TyBeginLoc = TypeRange.getBegin();
|
SourceLocation TyBeginLoc = TypeRange.getBegin();
|
||||||
SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
|
SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
|
||||||
|
|
||||||
|
if (Ty->isDependentType() ||
|
||||||
|
CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
|
||||||
|
return new (Context) CXXTemporaryObjectExpr(0, Ty, TyBeginLoc,
|
||||||
|
Exprs, NumExprs, RParenLoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// C++ [expr.type.conv]p1:
|
// C++ [expr.type.conv]p1:
|
||||||
// If the expression list is a single expression, the type conversion
|
// If the expression list is a single expression, the type conversion
|
||||||
// expression is equivalent (in definedness, and if defined in meaning) to the
|
// expression is equivalent (in definedness, and if defined in meaning) to the
|
||||||
|
@ -134,8 +141,6 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
|
||||||
TyBeginLoc, Exprs[0], RParenLoc);
|
TyBeginLoc, Exprs[0], RParenLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: What AST node to create when the type is dependent?
|
|
||||||
|
|
||||||
if (const RecordType *RT = Ty->getAsRecordType()) {
|
if (const RecordType *RT = Ty->getAsRecordType()) {
|
||||||
CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
|
CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
|
||||||
|
|
||||||
|
|
|
@ -1392,6 +1392,9 @@ static bool
|
||||||
IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
|
IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
|
||||||
QualType T1, QualType T2,
|
QualType T1, QualType T2,
|
||||||
ASTContext &Context) {
|
ASTContext &Context) {
|
||||||
|
if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
|
||||||
|
return true;
|
||||||
|
|
||||||
if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
|
if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -1275,7 +1275,14 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
||||||
QualType IntegerType = Context.getCanonicalType(ParamType);
|
QualType IntegerType = Context.getCanonicalType(ParamType);
|
||||||
if (const EnumType *Enum = IntegerType->getAsEnumType())
|
if (const EnumType *Enum = IntegerType->getAsEnumType())
|
||||||
IntegerType = Enum->getDecl()->getIntegerType();
|
IntegerType = Enum->getDecl()->getIntegerType();
|
||||||
|
|
||||||
|
if (Arg->isValueDependent()) {
|
||||||
|
// The argument is value-dependent. Create a new
|
||||||
|
// TemplateArgument with the converted expression.
|
||||||
|
Converted->push_back(TemplateArgument(Arg));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
llvm::APInt CanonicalArg(Context.getTypeSize(IntegerType), 0,
|
llvm::APInt CanonicalArg(Context.getTypeSize(IntegerType), 0,
|
||||||
IntegerType->isSignedIntegerType());
|
IntegerType->isSignedIntegerType());
|
||||||
CanonicalArg = Value;
|
CanonicalArg = Value;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "clang/AST/DeclTemplate.h"
|
#include "clang/AST/DeclTemplate.h"
|
||||||
#include "clang/AST/StmtVisitor.h"
|
#include "clang/AST/StmtVisitor.h"
|
||||||
#include "clang/Parse/DeclSpec.h"
|
#include "clang/Parse/DeclSpec.h"
|
||||||
|
#include "clang/Lex/Preprocessor.h" // for the identifier table
|
||||||
#include "clang/Basic/LangOptions.h"
|
#include "clang/Basic/LangOptions.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
|
|
||||||
|
@ -441,7 +442,12 @@ InstantiateClassTemplateSpecializationType(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TemplateArgument::Expression:
|
case TemplateArgument::Expression:
|
||||||
assert(false && "Cannot instantiate expressions yet");
|
Sema::OwningExprResult E
|
||||||
|
= SemaRef.InstantiateExpr(Arg->getAsExpr(), TemplateArgs,
|
||||||
|
NumTemplateArgs);
|
||||||
|
if (E.isInvalid())
|
||||||
|
return QualType();
|
||||||
|
InstantiatedTemplateArgs.push_back((Expr *)E.release());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -564,6 +570,8 @@ namespace {
|
||||||
unsigned NumTemplateArgs;
|
unsigned NumTemplateArgs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef Sema::OwningExprResult OwningExprResult;
|
||||||
|
|
||||||
TemplateExprInstantiator(Sema &SemaRef,
|
TemplateExprInstantiator(Sema &SemaRef,
|
||||||
const TemplateArgument *TemplateArgs,
|
const TemplateArgument *TemplateArgs,
|
||||||
unsigned NumTemplateArgs)
|
unsigned NumTemplateArgs)
|
||||||
|
@ -573,11 +581,13 @@ namespace {
|
||||||
// FIXME: Once we get closer to completion, replace these
|
// FIXME: Once we get closer to completion, replace these
|
||||||
// manually-written declarations with automatically-generated ones
|
// manually-written declarations with automatically-generated ones
|
||||||
// from clang/AST/StmtNodes.def.
|
// from clang/AST/StmtNodes.def.
|
||||||
Sema::OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
|
OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
|
||||||
Sema::OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
|
OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
|
||||||
Sema::OwningExprResult VisitParenExpr(ParenExpr *E);
|
OwningExprResult VisitParenExpr(ParenExpr *E);
|
||||||
Sema::OwningExprResult VisitBinaryOperator(BinaryOperator *E);
|
OwningExprResult VisitBinaryOperator(BinaryOperator *E);
|
||||||
Sema::OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
|
OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
|
||||||
|
OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
|
||||||
|
OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
|
||||||
|
|
||||||
// Base case. I'm supposed to ignore this.
|
// Base case. I'm supposed to ignore this.
|
||||||
Sema::OwningExprResult VisitStmt(Stmt *) {
|
Sema::OwningExprResult VisitStmt(Stmt *) {
|
||||||
|
@ -692,6 +702,9 @@ TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
||||||
DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee());
|
DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee());
|
||||||
OverloadedFunctionDecl *Overloads
|
OverloadedFunctionDecl *Overloads
|
||||||
= cast<OverloadedFunctionDecl>(DRE->getDecl());
|
= cast<OverloadedFunctionDecl>(DRE->getDecl());
|
||||||
|
|
||||||
|
// FIXME: Do we have to check
|
||||||
|
// IsAcceptableNonMemberOperatorCandidate for each of these?
|
||||||
for (OverloadedFunctionDecl::function_iterator
|
for (OverloadedFunctionDecl::function_iterator
|
||||||
F = Overloads->function_begin(),
|
F = Overloads->function_begin(),
|
||||||
FEnd = Overloads->function_end();
|
FEnd = Overloads->function_end();
|
||||||
|
@ -716,6 +729,90 @@ TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
||||||
return move(Result);
|
return move(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sema::OwningExprResult
|
||||||
|
TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
|
||||||
|
bool isSizeOf = E->isSizeOf();
|
||||||
|
|
||||||
|
if (E->isArgumentType()) {
|
||||||
|
QualType T = E->getArgumentType();
|
||||||
|
if (T->isDependentType()) {
|
||||||
|
T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
|
||||||
|
/*FIXME*/E->getOperatorLoc(),
|
||||||
|
&SemaRef.PP.getIdentifierTable().get("sizeof"));
|
||||||
|
if (T.isNull())
|
||||||
|
return SemaRef.ExprError();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SemaRef.CreateSizeOfAlignOfExpr(T, E->getOperatorLoc(), isSizeOf,
|
||||||
|
E->getSourceRange());
|
||||||
|
}
|
||||||
|
|
||||||
|
Sema::OwningExprResult Arg = Visit(E->getArgumentExpr());
|
||||||
|
if (Arg.isInvalid())
|
||||||
|
return SemaRef.ExprError();
|
||||||
|
|
||||||
|
Sema::OwningExprResult Result
|
||||||
|
= SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
|
||||||
|
isSizeOf, E->getSourceRange());
|
||||||
|
if (Result.isInvalid())
|
||||||
|
return SemaRef.ExprError();
|
||||||
|
|
||||||
|
Arg.release();
|
||||||
|
return move(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sema::OwningExprResult
|
||||||
|
TemplateExprInstantiator::VisitCXXTemporaryObjectExpr(
|
||||||
|
CXXTemporaryObjectExpr *E) {
|
||||||
|
QualType T = E->getType();
|
||||||
|
if (T->isDependentType()) {
|
||||||
|
T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
|
||||||
|
E->getTypeBeginLoc(), DeclarationName());
|
||||||
|
if (T.isNull())
|
||||||
|
return SemaRef.ExprError();
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::SmallVector<Expr *, 16> Args;
|
||||||
|
Args.reserve(E->getNumArgs());
|
||||||
|
bool Invalid = false;
|
||||||
|
for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(),
|
||||||
|
ArgEnd = E->arg_end();
|
||||||
|
Arg != ArgEnd; ++Arg) {
|
||||||
|
OwningExprResult InstantiatedArg = Visit(*Arg);
|
||||||
|
if (InstantiatedArg.isInvalid()) {
|
||||||
|
Invalid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Args.push_back((Expr *)InstantiatedArg.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Invalid) {
|
||||||
|
SourceLocation CommaLoc;
|
||||||
|
// FIXME: HACK!
|
||||||
|
if (Args.size() > 1)
|
||||||
|
CommaLoc
|
||||||
|
= SemaRef.PP.getLocForEndOfToken(Args[0]->getSourceRange().getEnd());
|
||||||
|
Sema::ExprResult Result
|
||||||
|
= SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()
|
||||||
|
/*, FIXME*/),
|
||||||
|
T.getAsOpaquePtr(),
|
||||||
|
/*FIXME*/E->getTypeBeginLoc(),
|
||||||
|
(void**)&Args[0], Args.size(),
|
||||||
|
/*HACK*/&CommaLoc,
|
||||||
|
E->getSourceRange().getEnd());
|
||||||
|
if (!Result.isInvalid())
|
||||||
|
return SemaRef.Owned(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up the instantiated arguments.
|
||||||
|
// FIXME: Would rather do this with RAII.
|
||||||
|
for (unsigned Idx = 0; Idx < Args.size(); ++Idx)
|
||||||
|
SemaRef.DeleteExpr(Args[Idx]);
|
||||||
|
|
||||||
|
return SemaRef.ExprError();
|
||||||
|
}
|
||||||
|
|
||||||
Sema::OwningExprResult
|
Sema::OwningExprResult
|
||||||
Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
|
Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
|
||||||
unsigned NumTemplateArgs) {
|
unsigned NumTemplateArgs) {
|
||||||
|
|
|
@ -43,3 +43,13 @@ void test_BitfieldDivide() {
|
||||||
(void)sizeof(BitfieldDivide<5, 1>);
|
(void)sizeof(BitfieldDivide<5, 1>);
|
||||||
(void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'struct BitfieldDivide<5, 0>' requested here}}
|
(void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'struct BitfieldDivide<5, 0>' requested here}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, T I, int J>
|
||||||
|
struct BitfieldDep {
|
||||||
|
int bitfield : I + J;
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_BitfieldDep() {
|
||||||
|
(void)sizeof(BitfieldDep<int, 1, 5>);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue