diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprCXX.cpp | 5 | ||||
-rw-r--r-- | lib/AST/StmtSerialization.cpp | 11 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 90 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 109 |
9 files changed, 200 insertions, 50 deletions
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 184c9fe490..1d4a3ba3a6 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -216,7 +216,10 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, Expr **Args, unsigned NumArgs, SourceLocation rParenLoc) - : Expr(CXXTemporaryObjectExprClass, writtenTy), + : Expr(CXXTemporaryObjectExprClass, writtenTy, + writtenTy->isDependentType(), + (writtenTy->isDependentType() || + CallExpr::hasAnyValueDependentArguments(Args, NumArgs))), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc), Constructor(Cons), Args(0), NumArgs(NumArgs) { if (NumArgs > 0) { diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp index 4a90edd7a1..78366a1514 100644 --- a/lib/AST/StmtSerialization.cpp +++ b/lib/AST/StmtSerialization.cpp @@ -832,9 +832,14 @@ SizeOfAlignOfExpr::CreateImpl(Deserializer& D, ASTContext& C) { QualType Res = QualType::ReadVal(D); SourceLocation OpLoc = SourceLocation::ReadVal(D); SourceLocation RParenLoc = SourceLocation::ReadVal(D); - - return new SizeOfAlignOfExpr(isSizeof, isType, Argument, Res, - OpLoc, RParenLoc); + + if (isType) + 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 { diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1b7fc1be4a..fc71097c12 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -967,9 +967,12 @@ ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args, } void ClassTemplateSpecializationType::Destroy(ASTContext& C) { - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) - if (Expr *E = getArg(Arg).getAsExpr()) - E->Destroy(C); + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + // FIXME: Not all expressions get cloned, so we can't yet perform + // this destruction. + // if (Expr *E = getArg(Arg).getAsExpr()) + // E->Destroy(C); + } } ClassTemplateSpecializationType::iterator diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index c6fe6c164a..b29790e7b5 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1188,6 +1188,11 @@ public: ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, 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 CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc, const SourceRange &R, bool isSizeof); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0855932ac4..c04006cb1c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1220,6 +1220,50 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, 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 /// the same for @c alignof and @c __alignof /// 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 (TyOrEx == 0) return ExprError(); - QualType ArgTy; - SourceRange Range; if (isType) { - ArgTy = QualType::getFromOpaquePtr(TyOrEx); - Range = 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(); - } - } + QualType ArgTy = QualType::getFromOpaquePtr(TyOrEx); + return CreateSizeOfAlignOfExpr(ArgTy, OpLoc, isSizeof, ArgRange); + } - // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. - return Owned(new (Context) SizeOfAlignOfExpr(isSizeof, isType, TyOrEx, - Context.getSizeType(), OpLoc, - Range.getEnd())); + // Get the end location. + Expr *ArgEx = (Expr *)TyOrEx; + Action::OwningExprResult Result + = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange()); + + if (Result.isInvalid()) + DeleteExpr(ArgEx); + + return move(Result); } QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 501eda7443..e5a252043e 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -122,6 +122,13 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, SourceLocation TyBeginLoc = TypeRange.getBegin(); 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: // If the expression list is a single expression, the type conversion // 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); } - // FIXME: What AST node to create when the type is dependent? - if (const RecordType *RT = Ty->getAsRecordType()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index d391c07b3f..57683b30ec 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1392,6 +1392,9 @@ static bool IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, QualType T1, QualType T2, ASTContext &Context) { + if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType())) + return true; + if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType())) return true; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 6fc4515571..3780259d43 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1275,7 +1275,14 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType IntegerType = Context.getCanonicalType(ParamType); if (const EnumType *Enum = IntegerType->getAsEnumType()) 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, IntegerType->isSignedIntegerType()); CanonicalArg = Value; diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index b3e4148a6a..4bd7ad4e83 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/StmtVisitor.h" #include "clang/Parse/DeclSpec.h" +#include "clang/Lex/Preprocessor.h" // for the identifier table #include "clang/Basic/LangOptions.h" #include "llvm/Support/Compiler.h" @@ -441,7 +442,12 @@ InstantiateClassTemplateSpecializationType( break; 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; } } @@ -564,6 +570,8 @@ namespace { unsigned NumTemplateArgs; public: + typedef Sema::OwningExprResult OwningExprResult; + TemplateExprInstantiator(Sema &SemaRef, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) @@ -573,11 +581,13 @@ namespace { // FIXME: Once we get closer to completion, replace these // manually-written declarations with automatically-generated ones // from clang/AST/StmtNodes.def. - Sema::OwningExprResult VisitIntegerLiteral(IntegerLiteral *E); - Sema::OwningExprResult VisitDeclRefExpr(DeclRefExpr *E); - Sema::OwningExprResult VisitParenExpr(ParenExpr *E); - Sema::OwningExprResult VisitBinaryOperator(BinaryOperator *E); - Sema::OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); + OwningExprResult VisitIntegerLiteral(IntegerLiteral *E); + OwningExprResult VisitDeclRefExpr(DeclRefExpr *E); + OwningExprResult VisitParenExpr(ParenExpr *E); + OwningExprResult VisitBinaryOperator(BinaryOperator *E); + OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); + OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); + OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); // Base case. I'm supposed to ignore this. Sema::OwningExprResult VisitStmt(Stmt *) { @@ -692,6 +702,9 @@ TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee()); OverloadedFunctionDecl *Overloads = cast<OverloadedFunctionDecl>(DRE->getDecl()); + + // FIXME: Do we have to check + // IsAcceptableNonMemberOperatorCandidate for each of these? for (OverloadedFunctionDecl::function_iterator F = Overloads->function_begin(), FEnd = Overloads->function_end(); @@ -717,6 +730,90 @@ TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { } 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::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { TemplateExprInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs); |