diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-05-19 22:10:17 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-05-19 22:10:17 +0000 |
commit | cde01739dffe574c53a6ba1def1a57a2cc7b4a8b (patch) | |
tree | 54b9645e4b7dc65cf487b39484415dd66dff0ad6 | |
parent | d1f22e1f73b67116393720739d3ab8116ae301bc (diff) |
Template instantiation for __builtin_shufflevector.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72139 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 102 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateExpr.cpp | 48 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-expr-3.cpp | 16 |
4 files changed, 138 insertions, 33 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 9df087ae68..f5c4a7bb63 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2708,7 +2708,12 @@ private: bool SemaBuiltinVAStart(CallExpr *TheCall); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); bool SemaBuiltinStackAddress(CallExpr *TheCall); + +public: + // Used by C++ template instantiation. Action::OwningExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); + +private: bool SemaBuiltinPrefetch(CallExpr *TheCall); bool SemaBuiltinObjectSize(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index a76463fac8..5a68346e0d 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -501,7 +501,7 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { Expr *OrigArg0 = TheCall->getArg(0); Expr *OrigArg1 = TheCall->getArg(1); - + // Do standard promotions between the two arguments, returning their common // type. QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); @@ -512,6 +512,9 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { TheCall->setArg(0, OrigArg0); TheCall->setArg(1, OrigArg1); + if (OrigArg0->isTypeDependent() || OrigArg1->isTypeDependent()) + return false; + // If the common type isn't a real floating type, then the arguments were // invalid for this operation. if (!Res->isRealFloatingType()) @@ -527,7 +530,9 @@ bool Sema::SemaBuiltinStackAddress(CallExpr *TheCall) { // The signature for these builtins is exact; the only thing we need // to check is that the argument is a constant. SourceLocation Loc; - if (!TheCall->getArg(0)->isIntegerConstantExpr(Context, &Loc)) + if (!TheCall->getArg(0)->isTypeDependent() && + !TheCall->getArg(0)->isValueDependent() && + !TheCall->getArg(0)->isIntegerConstantExpr(Context, &Loc)) return Diag(Loc, diag::err_stack_const_level) << TheCall->getSourceRange(); return false; @@ -541,36 +546,44 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { diag::err_typecheck_call_too_few_args) << 0 /*function call*/ << TheCall->getSourceRange()); - QualType FAType = TheCall->getArg(0)->getType(); - QualType SAType = TheCall->getArg(1)->getType(); - - if (!FAType->isVectorType() || !SAType->isVectorType()) { - Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector) - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - return ExprError(); - } - - if (Context.getCanonicalType(FAType).getUnqualifiedType() != - Context.getCanonicalType(SAType).getUnqualifiedType()) { - Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - return ExprError(); - } + unsigned numElements = std::numeric_limits<unsigned>::max(); + if (!TheCall->getArg(0)->isTypeDependent() && + !TheCall->getArg(1)->isTypeDependent()) { + QualType FAType = TheCall->getArg(0)->getType(); + QualType SAType = TheCall->getArg(1)->getType(); + + if (!FAType->isVectorType() || !SAType->isVectorType()) { + Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector) + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + return ExprError(); + } + + if (Context.getCanonicalType(FAType).getUnqualifiedType() != + Context.getCanonicalType(SAType).getUnqualifiedType()) { + Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + return ExprError(); + } - unsigned numElements = FAType->getAsVectorType()->getNumElements(); - if (TheCall->getNumArgs() != numElements+2) { - if (TheCall->getNumArgs() < numElements+2) + numElements = FAType->getAsVectorType()->getNumElements(); + if (TheCall->getNumArgs() != numElements+2) { + if (TheCall->getNumArgs() < numElements+2) + return ExprError(Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args) + << 0 /*function call*/ << TheCall->getSourceRange()); return ExprError(Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args) - << 0 /*function call*/ << TheCall->getSourceRange()); - return ExprError(Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << TheCall->getSourceRange()); + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << TheCall->getSourceRange()); + } } for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { + if (TheCall->getArg(i)->isTypeDependent() || + TheCall->getArg(i)->isValueDependent()) + continue; + llvm::APSInt Result(32); if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) return ExprError(Diag(TheCall->getLocStart(), @@ -590,8 +603,8 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { TheCall->setArg(i, 0); } - return Owned(new (Context) ShuffleVectorExpr(exprs.begin(), numElements+2, - FAType, + return Owned(new (Context) ShuffleVectorExpr(exprs.begin(), exprs.size(), + exprs[0]->getType(), TheCall->getCallee()->getLocStart(), TheCall->getRParenLoc())); } @@ -610,14 +623,23 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { // constant integers. for (unsigned i = 1; i != NumArgs; ++i) { Expr *Arg = TheCall->getArg(i); + if (Arg->isTypeDependent()) + continue; + QualType RWType = Arg->getType(); const BuiltinType *BT = RWType->getAsBuiltinType(); llvm::APSInt Result; - if (!BT || BT->getKind() != BuiltinType::Int || - !Arg->isIntegerConstantExpr(Result, Context)) + if (!BT || BT->getKind() != BuiltinType::Int) return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_argument) << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + + if (Arg->isValueDependent()) + continue; + + if (!Arg->isIntegerConstantExpr(Result, Context)) + return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_argument) + << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); // FIXME: gcc issues a warning and rewrites these to 0. These // seems especially odd for the third argument since the default @@ -641,11 +663,20 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { /// constants (0-3). bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { Expr *Arg = TheCall->getArg(1); + if (Arg->isTypeDependent()) + return false; + QualType ArgType = Arg->getType(); const BuiltinType *BT = ArgType->getAsBuiltinType(); llvm::APSInt Result(32); - if (!BT || BT->getKind() != BuiltinType::Int || - !Arg->isIntegerConstantExpr(Result, Context)) { + if (!BT || BT->getKind() != BuiltinType::Int) + return Diag(TheCall->getLocStart(), diag::err_object_size_invalid_argument) + << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + + if (Arg->isValueDependent()) + return false; + + if (!Arg->isIntegerConstantExpr(Result, Context)) { return Diag(TheCall->getLocStart(), diag::err_object_size_invalid_argument) << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); } @@ -662,6 +693,9 @@ bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { /// This checks that val is a constant 1. bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { Expr *Arg = TheCall->getArg(1); + if (Arg->isTypeDependent() || Arg->isValueDependent()) + return false; + llvm::APSInt Result(32); if (!Arg->isIntegerConstantExpr(Result, Context) || Result != 1) return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val) @@ -674,6 +708,8 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg) { + if (E->isTypeDependent() || E->isValueDependent()) + return false; switch (E->getStmtClass()) { case Stmt::ConditionalOperatorClass: { diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index fde3110234..5e91ada66d 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -57,6 +57,7 @@ namespace { // FIXME: AddrLabelExpr OwningExprResult VisitStmtExpr(StmtExpr *E); OwningExprResult VisitTypesCompatibleExpr(TypesCompatibleExpr *E); + OwningExprResult VisitShuffleVectorExpr(ShuffleVectorExpr *E); OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); OwningExprResult VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E); OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); @@ -487,6 +488,53 @@ TemplateExprInstantiator::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) { } Sema::OwningExprResult +TemplateExprInstantiator::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { + // FIXME: Better solution for this! + llvm::SmallVector<Expr *, 8> SubExprs; + for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) { + OwningExprResult SubExpr = Visit(E->getExpr(I)); + if (SubExpr.isInvalid()) { + for (unsigned Victim = 0; Victim != I; ++Victim) + SubExprs[I]->Destroy(SemaRef.Context); + return SemaRef.ExprError(); + } + + SubExprs.push_back(SubExpr.takeAs<Expr>()); + } + + // Find the declaration for __builtin_shufflevector + const IdentifierInfo &Name + = SemaRef.Context.Idents.get("__builtin_shufflevector"); + TranslationUnitDecl *TUDecl = SemaRef.Context.getTranslationUnitDecl(); + DeclContext::lookup_result Lookup + = TUDecl->lookup(SemaRef.Context, DeclarationName(&Name)); + assert(Lookup.first != Lookup.second && "No __builtin_shufflevector?"); + + // Build a reference to the __builtin_shufflevector builtin + FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first); + Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), + E->getBuiltinLoc(), + false, false); + SemaRef.UsualUnaryConversions(Callee); + + // Build the CallExpr + CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, + &SubExprs[0], + SubExprs.size(), + Builtin->getResultType(), + E->getRParenLoc()); + OwningExprResult OwnedCall(SemaRef.Owned(TheCall)); + + // Type-check the __builtin_shufflevector expression. + OwningExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall); + if (Result.isInvalid()) + return SemaRef.ExprError(); + + OwnedCall.release(); + return move(Result); +} + +Sema::OwningExprResult TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { bool isSizeOf = E->isSizeOf(); diff --git a/test/SemaTemplate/instantiate-expr-3.cpp b/test/SemaTemplate/instantiate-expr-3.cpp index bc1097c5aa..a17897b085 100644 --- a/test/SemaTemplate/instantiate-expr-3.cpp +++ b/test/SemaTemplate/instantiate-expr-3.cpp @@ -81,3 +81,19 @@ struct TypesCompatible0 { }; template struct TypesCompatible0<int, const int, true>; + +// --------------------------------------------------------------------- +// __builtin_shufflevector +// --------------------------------------------------------------------- +typedef __attribute__(( ext_vector_type(2) )) double double2; +template<typename T, typename U, int N, int M> +struct ShuffleVector0 { + void f(T t, U u, double2 a, double2 b) { + (void)__builtin_shufflevector(t, u, N, M); // expected-error{{index}} + (void)__builtin_shufflevector(a, b, N, M); + (void)__builtin_shufflevector(a, b, 2, 1); + } +}; + +template struct ShuffleVector0<double2, double2, 2, 1>; +template struct ShuffleVector0<double2, double2, 4, 3>; // expected-note{{instantiation}} |