aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-05-19 22:10:17 +0000
committerDouglas Gregor <dgregor@apple.com>2009-05-19 22:10:17 +0000
commitcde01739dffe574c53a6ba1def1a57a2cc7b4a8b (patch)
tree54b9645e4b7dc65cf487b39484415dd66dff0ad6
parentd1f22e1f73b67116393720739d3ab8116ae301bc (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.h5
-rw-r--r--lib/Sema/SemaChecking.cpp102
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp48
-rw-r--r--test/SemaTemplate/instantiate-expr-3.cpp16
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}}