summaryrefslogtreecommitdiff
path: root/lib/AST/Expr.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:37 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:37 +0000
commit461a67fa15370a9ec88f8f8a240bf7c123bb2029 (patch)
tree6942083d7d56bba40ec790a453ca58ad3baf6832 /lib/AST/Expr.cpp
parent75c3240472ba6ac2669ee72ca67eb72d4e2851fc (diff)
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r--lib/AST/Expr.cpp116
1 files changed, 101 insertions, 15 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index afc7fa8ea0949..55061aa462e5c 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1695,6 +1695,26 @@ CXXBaseSpecifier **CastExpr::path_buffer() {
}
}
+const FieldDecl *CastExpr::getTargetFieldForToUnionCast(QualType unionType,
+ QualType opType) {
+ auto RD = unionType->castAs<RecordType>()->getDecl();
+ return getTargetFieldForToUnionCast(RD, opType);
+}
+
+const FieldDecl *CastExpr::getTargetFieldForToUnionCast(const RecordDecl *RD,
+ QualType OpType) {
+ auto &Ctx = RD->getASTContext();
+ RecordDecl::field_iterator Field, FieldEnd;
+ for (Field = RD->field_begin(), FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ if (Ctx.hasSameUnqualifiedType(Field->getType(), OpType) &&
+ !Field->isUnnamedBitfield()) {
+ return *Field;
+ }
+ }
+ return nullptr;
+}
+
ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
CastKind Kind, Expr *Operand,
const CXXCastPath *BasePath,
@@ -1760,6 +1780,7 @@ BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
case OO_Amp: return BO_And;
case OO_Pipe: return BO_Or;
case OO_Equal: return BO_Assign;
+ case OO_Spaceship: return BO_Cmp;
case OO_Less: return BO_LT;
case OO_Greater: return BO_GT;
case OO_PlusEqual: return BO_AddAssign;
@@ -1791,6 +1812,7 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
OO_Star, OO_Slash, OO_Percent,
OO_Plus, OO_Minus,
OO_LessLess, OO_GreaterGreater,
+ OO_Spaceship,
OO_Less, OO_Greater, OO_LessEqual, OO_GreaterEqual,
OO_EqualEqual, OO_ExclaimEqual,
OO_Amp,
@@ -1809,6 +1831,38 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
return OverOps[Opc];
}
+bool BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx,
+ Opcode Opc,
+ Expr *LHS, Expr *RHS) {
+ if (Opc != BO_Add)
+ return false;
+
+ // Check that we have one pointer and one integer operand.
+ Expr *PExp;
+ if (LHS->getType()->isPointerType()) {
+ if (!RHS->getType()->isIntegerType())
+ return false;
+ PExp = LHS;
+ } else if (RHS->getType()->isPointerType()) {
+ if (!LHS->getType()->isIntegerType())
+ return false;
+ PExp = RHS;
+ } else {
+ return false;
+ }
+
+ // Check that the pointer is a nullptr.
+ if (!PExp->IgnoreParenCasts()
+ ->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
+ return false;
+
+ // Check that the pointee type is char-sized.
+ const PointerType *PTy = PExp->getType()->getAs<PointerType>();
+ if (!PTy || !PTy->getPointeeType()->isCharType())
+ return false;
+
+ return true;
+}
InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
ArrayRef<Expr*> initExprs, SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
@@ -1899,6 +1953,17 @@ bool InitListExpr::isTransparent() const {
getInit(0)->getType().getCanonicalType();
}
+bool InitListExpr::isIdiomaticZeroInitializer(const LangOptions &LangOpts) const {
+ assert(isSyntacticForm() && "only test syntactic form as zero initializer");
+
+ if (LangOpts.CPlusPlus || getNumInits() != 1) {
+ return false;
+ }
+
+ const IntegerLiteral *Lit = dyn_cast<IntegerLiteral>(getInit(0));
+ return Lit && Lit->getValue() == 0;
+}
+
SourceLocation InitListExpr::getLocStart() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
return SyntacticForm->getLocStart();
@@ -2235,7 +2300,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
const DeclRefExpr *DRE =
dyn_cast<DeclRefExpr>(CE->getSubExpr()->IgnoreParens());
if (!(DRE && isa<VarDecl>(DRE->getDecl()) &&
- cast<VarDecl>(DRE->getDecl())->hasLocalStorage())) {
+ cast<VarDecl>(DRE->getDecl())->hasLocalStorage()) &&
+ !isa<CallExpr>(CE->getSubExpr()->IgnoreParens())) {
return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc,
R1, R2, Ctx);
}
@@ -3230,20 +3296,20 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
// Check that it is a cast to void*.
if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
QualType Pointee = PT->getPointeeType();
- Qualifiers Q = Pointee.getQualifiers();
- // In OpenCL v2.0 generic address space acts as a placeholder
- // and should be ignored.
- bool IsASValid = true;
- if (Ctx.getLangOpts().OpenCLVersion >= 200) {
- if (Pointee.getAddressSpace() == LangAS::opencl_generic)
- Q.removeAddressSpace();
- else
- IsASValid = false;
- }
-
- if (IsASValid && !Q.hasQualifiers() &&
- Pointee->isVoidType() && // to void*
- CE->getSubExpr()->getType()->isIntegerType()) // from int.
+ // Only (void*)0 or equivalent are treated as nullptr. If pointee type
+ // has non-default address space it is not treated as nullptr.
+ // (__generic void*)0 in OpenCL 2.0 should not be treated as nullptr
+ // since it cannot be assigned to a pointer to constant address space.
+ bool PointeeHasDefaultAS =
+ Pointee.getAddressSpace() == LangAS::Default ||
+ (Ctx.getLangOpts().OpenCLVersion >= 200 &&
+ Pointee.getAddressSpace() == LangAS::opencl_generic) ||
+ (Ctx.getLangOpts().OpenCL &&
+ Ctx.getLangOpts().OpenCLVersion < 200 &&
+ Pointee.getAddressSpace() == LangAS::opencl_private);
+
+ if (PointeeHasDefaultAS && Pointee->isVoidType() && // to void*
+ CE->getSubExpr()->getType()->isIntegerType()) // from int.
return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
}
}
@@ -3938,10 +4004,12 @@ AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args,
unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
switch (Op) {
case AO__c11_atomic_init:
+ case AO__opencl_atomic_init:
case AO__c11_atomic_load:
case AO__atomic_load_n:
return 2;
+ case AO__opencl_atomic_load:
case AO__c11_atomic_store:
case AO__c11_atomic_exchange:
case AO__atomic_load:
@@ -3967,6 +4035,15 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__atomic_nand_fetch:
return 3;
+ case AO__opencl_atomic_store:
+ case AO__opencl_atomic_exchange:
+ case AO__opencl_atomic_fetch_add:
+ case AO__opencl_atomic_fetch_sub:
+ case AO__opencl_atomic_fetch_and:
+ case AO__opencl_atomic_fetch_or:
+ case AO__opencl_atomic_fetch_xor:
+ case AO__opencl_atomic_fetch_min:
+ case AO__opencl_atomic_fetch_max:
case AO__atomic_exchange:
return 4;
@@ -3974,6 +4051,8 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
case AO__c11_atomic_compare_exchange_weak:
return 5;
+ case AO__opencl_atomic_compare_exchange_strong:
+ case AO__opencl_atomic_compare_exchange_weak:
case AO__atomic_compare_exchange:
case AO__atomic_compare_exchange_n:
return 6;
@@ -3981,6 +4060,13 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
llvm_unreachable("unknown atomic op");
}
+QualType AtomicExpr::getValueType() const {
+ auto T = getPtr()->getType()->castAs<PointerType>()->getPointeeType();
+ if (auto AT = T->getAs<AtomicType>())
+ return AT->getValueType();
+ return T;
+}
+
QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) {
unsigned ArraySectionCount = 0;
while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) {