summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@apple.com>2011-11-08 05:04:11 +0000
committerBob Wilson <bob.wilson@apple.com>2011-11-08 05:04:11 +0000
commite4d7723b87fa480db6aa314b591f61a26b1f3278 (patch)
tree839ef7e4bfa40fe7b0f9a3c182bfa5fdc2305bb6 /clang/lib/Sema/SemaChecking.cpp
parent1f3966bebd9e08b40c6185b9b39938b5d06d5ef5 (diff)
downloadbcm5719-llvm-e4d7723b87fa480db6aa314b591f61a26b1f3278.tar.gz
bcm5719-llvm-e4d7723b87fa480db6aa314b591f61a26b1f3278.zip
Check pointer types for arguments of Neon load/store macros. rdar://9958031
The Neon load/store intrinsics need to be implemented as macros to avoid hiding alignment attributes on the pointer arguments, and the macros can only evaluate those pointer arguments once (in case they have side effects), so it has been hard to get the right type checking for those pointers. I tried various alternatives in the arm_neon.h header, but it's much more straightforward to just check directly in Sema. llvm-svn: 144075
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp57
1 files changed, 54 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 90b97380398..cd07358b159 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -268,11 +268,38 @@ static unsigned RFT(unsigned t, bool shift = false) {
return 0;
}
+/// getNeonEltType - Return the QualType corresponding to the elements of
+/// the vector type specified by the NeonTypeFlags. This is used to check
+/// the pointer arguments for Neon load/store intrinsics.
+static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context) {
+ switch (Flags.getEltType()) {
+ case NeonTypeFlags::Int8:
+ return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
+ case NeonTypeFlags::Int16:
+ return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
+ case NeonTypeFlags::Int32:
+ return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
+ case NeonTypeFlags::Int64:
+ return Flags.isUnsigned() ? Context.UnsignedLongLongTy : Context.LongLongTy;
+ case NeonTypeFlags::Poly8:
+ return Context.SignedCharTy;
+ case NeonTypeFlags::Poly16:
+ return Context.ShortTy;
+ case NeonTypeFlags::Float16:
+ return Context.UnsignedShortTy;
+ case NeonTypeFlags::Float32:
+ return Context.FloatTy;
+ }
+ return QualType();
+}
+
bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
llvm::APSInt Result;
unsigned mask = 0;
unsigned TV = 0;
+ bool HasPtr = false;
+ bool HasConstPtr = false;
switch (BuiltinID) {
#define GET_NEON_OVERLOAD_CHECK
#include "clang/Basic/arm_neon.inc"
@@ -281,15 +308,39 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
// For NEON intrinsics which are overloaded on vector element type, validate
// the immediate which specifies which variant to emit.
+ unsigned ImmArg = TheCall->getNumArgs()-1;
if (mask) {
- unsigned ArgNo = TheCall->getNumArgs()-1;
- if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
+ if (SemaBuiltinConstantArg(TheCall, ImmArg, Result))
return true;
TV = Result.getLimitedValue(64);
if ((TV > 63) || (mask & (1 << TV)) == 0)
return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
- << TheCall->getArg(ArgNo)->getSourceRange();
+ << TheCall->getArg(ImmArg)->getSourceRange();
+ }
+
+ if (HasPtr || HasConstPtr) {
+ // Check that pointer arguments have the specified type.
+ for (unsigned ArgNo = 0; ArgNo < ImmArg; ++ArgNo) {
+ Expr *Arg = TheCall->getArg(ArgNo);
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
+ Arg = ICE->getSubExpr();
+ ExprResult RHS = DefaultFunctionArrayLvalueConversion(Arg);
+ QualType RHSTy = RHS.get()->getType();
+ if (!RHSTy->isPointerType())
+ continue;
+ QualType EltTy = getNeonEltType(NeonTypeFlags(TV), Context);
+ if (HasConstPtr)
+ EltTy = EltTy.withConst();
+ QualType LHSTy = Context.getPointerType(EltTy);
+ AssignConvertType ConvTy;
+ ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
+ if (RHS.isInvalid())
+ return true;
+ if (DiagnoseAssignmentResult(ConvTy, Arg->getLocStart(), LHSTy, RHSTy,
+ RHS.get(), AA_Assigning))
+ return true;
+ }
}
// For NEON intrinsics which take an immediate value as part of the
OpenPOWER on IntegriCloud