| Chris Lattner | e13042c | 2008-07-11 19:10:17 +0000 | [diff] [blame] | 1 | //===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===// | 
| Anders Carlsson | 7a241ba | 2008-07-03 04:20:39 +0000 | [diff] [blame] | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | 4 | // See https://llvm.org/LICENSE.txt for license information. | 
|  | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| Anders Carlsson | 7a241ba | 2008-07-03 04:20:39 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 | // | 
|  | 9 | // This file implements the Expr constant evaluator. | 
|  | 10 | // | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 11 | // Constant expression evaluation produces four main results: | 
|  | 12 | // | 
|  | 13 | //  * A success/failure flag indicating whether constant folding was successful. | 
|  | 14 | //    This is the 'bool' return value used by most of the code in this file. A | 
|  | 15 | //    'false' return value indicates that constant folding has failed, and any | 
|  | 16 | //    appropriate diagnostic has already been produced. | 
|  | 17 | // | 
|  | 18 | //  * An evaluated result, valid only if constant folding has not failed. | 
|  | 19 | // | 
|  | 20 | //  * A flag indicating if evaluation encountered (unevaluated) side-effects. | 
|  | 21 | //    These arise in cases such as (sideEffect(), 0) and (sideEffect() || 1), | 
|  | 22 | //    where it is possible to determine the evaluated result regardless. | 
|  | 23 | // | 
|  | 24 | //  * A set of notes indicating why the evaluation was not a constant expression | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 25 | //    (under the C++11 / C++1y rules only, at the moment), or, if folding failed | 
|  | 26 | //    too, why the expression could not be folded. | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 27 | // | 
|  | 28 | // If we are checking for a potential constant expression, failure to constant | 
|  | 29 | // fold a potential constant sub-expression will be indicated by a 'false' | 
|  | 30 | // return value (the expression could not be folded) and no diagnostic (the | 
|  | 31 | // expression is not necessarily non-constant). | 
|  | 32 | // | 
| Anders Carlsson | 7a241ba | 2008-07-03 04:20:39 +0000 | [diff] [blame] | 33 | //===----------------------------------------------------------------------===// | 
|  | 34 |  | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 35 | #include <cstring> | 
|  | 36 | #include <functional> | 
|  | 37 | #include "Interp/Context.h" | 
|  | 38 | #include "Interp/Frame.h" | 
|  | 39 | #include "Interp/State.h" | 
| Anders Carlsson | 7a241ba | 2008-07-03 04:20:39 +0000 | [diff] [blame] | 40 | #include "clang/AST/APValue.h" | 
|  | 41 | #include "clang/AST/ASTContext.h" | 
| Benjamin Kramer | 444a130 | 2012-12-01 17:12:56 +0000 | [diff] [blame] | 42 | #include "clang/AST/ASTDiagnostic.h" | 
| Faisal Vali | a734ab9 | 2016-03-26 16:11:37 +0000 | [diff] [blame] | 43 | #include "clang/AST/ASTLambda.h" | 
| Nandor Licker | 7bd0a78 | 2019-08-29 21:57:47 +0000 | [diff] [blame] | 44 | #include "clang/AST/CXXInheritance.h" | 
| Ken Dyck | 4077500 | 2010-01-11 17:06:35 +0000 | [diff] [blame] | 45 | #include "clang/AST/CharUnits.h" | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 46 | #include "clang/AST/CurrentSourceLocExprScope.h" | 
| Benjamin Kramer | 444a130 | 2012-12-01 17:12:56 +0000 | [diff] [blame] | 47 | #include "clang/AST/Expr.h" | 
| Tim Northover | 314fbfa | 2018-11-02 13:14:11 +0000 | [diff] [blame] | 48 | #include "clang/AST/OSLog.h" | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 49 | #include "clang/AST/OptionalDiagnostic.h" | 
| Anders Carlsson | 15b73de | 2009-07-18 19:43:29 +0000 | [diff] [blame] | 50 | #include "clang/AST/RecordLayout.h" | 
| Seo Sanghyeon | 1904f44 | 2008-07-08 07:23:12 +0000 | [diff] [blame] | 51 | #include "clang/AST/StmtVisitor.h" | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 52 | #include "clang/AST/TypeLoc.h" | 
| Chris Lattner | 15ba949 | 2009-06-14 01:54:56 +0000 | [diff] [blame] | 53 | #include "clang/Basic/Builtins.h" | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 54 | #include "clang/Basic/FixedPoint.h" | 
| Anders Carlsson | 374b93d | 2008-07-08 05:49:43 +0000 | [diff] [blame] | 55 | #include "clang/Basic/TargetInfo.h" | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 56 | #include "llvm/ADT/Optional.h" | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 57 | #include "llvm/ADT/SmallBitVector.h" | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 58 | #include "llvm/Support/SaveAndRestore.h" | 
| Benjamin Kramer | 444a130 | 2012-12-01 17:12:56 +0000 | [diff] [blame] | 59 | #include "llvm/Support/raw_ostream.h" | 
| Mike Stump | 2346cd2 | 2009-05-30 03:56:50 +0000 | [diff] [blame] | 60 |  | 
| Ivan A. Kosarev | 01df519 | 2018-02-14 13:10:35 +0000 | [diff] [blame] | 61 | #define DEBUG_TYPE "exprconstant" | 
|  | 62 |  | 
| Anders Carlsson | 7a241ba | 2008-07-03 04:20:39 +0000 | [diff] [blame] | 63 | using namespace clang; | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 64 | using llvm::APInt; | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 65 | using llvm::APSInt; | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 66 | using llvm::APFloat; | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 67 | using llvm::Optional; | 
| Anders Carlsson | 7a241ba | 2008-07-03 04:20:39 +0000 | [diff] [blame] | 68 |  | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 69 | namespace { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 70 | struct LValue; | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 71 | class CallStackFrame; | 
|  | 72 | class EvalInfo; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 73 |  | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 74 | using SourceLocExprScopeGuard = | 
|  | 75 | CurrentSourceLocExprScope::SourceLocExprScopeGuard; | 
|  | 76 |  | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 77 | static QualType getType(APValue::LValueBase B) { | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 78 | if (!B) return QualType(); | 
| Richard Smith | 69cf59e | 2018-03-09 02:00:01 +0000 | [diff] [blame] | 79 | if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) { | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 80 | // FIXME: It's unclear where we're supposed to take the type from, and | 
| Richard Smith | 69cf59e | 2018-03-09 02:00:01 +0000 | [diff] [blame] | 81 | // this actually matters for arrays of unknown bound. Eg: | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 82 | // | 
|  | 83 | // extern int arr[]; void f() { extern int arr[3]; }; | 
|  | 84 | // constexpr int *p = &arr[1]; // valid? | 
| Richard Smith | 69cf59e | 2018-03-09 02:00:01 +0000 | [diff] [blame] | 85 | // | 
|  | 86 | // For now, we take the array bound from the most recent declaration. | 
|  | 87 | for (auto *Redecl = cast<ValueDecl>(D->getMostRecentDecl()); Redecl; | 
|  | 88 | Redecl = cast_or_null<ValueDecl>(Redecl->getPreviousDecl())) { | 
|  | 89 | QualType T = Redecl->getType(); | 
|  | 90 | if (!T->isIncompleteArrayType()) | 
|  | 91 | return T; | 
|  | 92 | } | 
|  | 93 | return D->getType(); | 
|  | 94 | } | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 95 |  | 
| Mikael Holmen | 3b6b2e3 | 2019-05-20 11:38:33 +0000 | [diff] [blame] | 96 | if (B.is<TypeInfoLValue>()) | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 97 | return B.getTypeInfoType(); | 
|  | 98 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 99 | if (B.is<DynamicAllocLValue>()) | 
|  | 100 | return B.getDynamicAllocType(); | 
|  | 101 |  | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 102 | const Expr *Base = B.get<const Expr*>(); | 
|  | 103 |  | 
|  | 104 | // For a materialized temporary, the type of the temporary we materialized | 
|  | 105 | // may not be the type of the expression. | 
|  | 106 | if (const MaterializeTemporaryExpr *MTE = | 
|  | 107 | dyn_cast<MaterializeTemporaryExpr>(Base)) { | 
|  | 108 | SmallVector<const Expr *, 2> CommaLHSs; | 
|  | 109 | SmallVector<SubobjectAdjustment, 2> Adjustments; | 
| Tyker | b0561b3 | 2019-11-17 11:41:55 +0100 | [diff] [blame] | 110 | const Expr *Temp = MTE->getSubExpr(); | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 111 | const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, | 
|  | 112 | Adjustments); | 
|  | 113 | // Keep any cv-qualifiers from the reference if we generated a temporary | 
| Richard Smith | b8c0f55 | 2016-12-09 18:49:13 +0000 | [diff] [blame] | 114 | // for it directly. Otherwise use the type after adjustment. | 
|  | 115 | if (!Adjustments.empty()) | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 116 | return Inner->getType(); | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | return Base->getType(); | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 120 | } | 
|  | 121 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 122 | /// Get an LValue path entry, which is known to not be an array index, as a | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 123 | /// field declaration. | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 124 | static const FieldDecl *getAsField(APValue::LValuePathEntry E) { | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 125 | return dyn_cast_or_null<FieldDecl>(E.getAsBaseOrMember().getPointer()); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 126 | } | 
|  | 127 | /// Get an LValue path entry, which is known to not be an array index, as a | 
|  | 128 | /// base class declaration. | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 129 | static const CXXRecordDecl *getAsBaseClass(APValue::LValuePathEntry E) { | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 130 | return dyn_cast_or_null<CXXRecordDecl>(E.getAsBaseOrMember().getPointer()); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 131 | } | 
|  | 132 | /// Determine whether this LValue path entry for a base class names a virtual | 
|  | 133 | /// base class. | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 134 | static bool isVirtualBaseClass(APValue::LValuePathEntry E) { | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 135 | return E.getAsBaseOrMember().getInt(); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 136 | } | 
|  | 137 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 138 | /// Given an expression, determine the type used to store the result of | 
|  | 139 | /// evaluating that expression. | 
| Richard Smith | 5769440 | 2019-10-08 23:37:49 +0000 | [diff] [blame] | 140 | static QualType getStorageType(const ASTContext &Ctx, const Expr *E) { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 141 | if (E->isRValue()) | 
|  | 142 | return E->getType(); | 
|  | 143 | return Ctx.getLValueReferenceType(E->getType()); | 
|  | 144 | } | 
|  | 145 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 146 | /// Given a CallExpr, try to get the alloc_size attribute. May return null. | 
|  | 147 | static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) { | 
|  | 148 | const FunctionDecl *Callee = CE->getDirectCallee(); | 
|  | 149 | return Callee ? Callee->getAttr<AllocSizeAttr>() : nullptr; | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 | /// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr. | 
|  | 153 | /// This will look through a single cast. | 
|  | 154 | /// | 
|  | 155 | /// Returns null if we couldn't unwrap a function with alloc_size. | 
|  | 156 | static const CallExpr *tryUnwrapAllocSizeCall(const Expr *E) { | 
|  | 157 | if (!E->getType()->isPointerType()) | 
|  | 158 | return nullptr; | 
|  | 159 |  | 
|  | 160 | E = E->IgnoreParens(); | 
|  | 161 | // If we're doing a variable assignment from e.g. malloc(N), there will | 
| George Burgess IV | 4763876 | 2018-03-07 04:52:34 +0000 | [diff] [blame] | 162 | // probably be a cast of some kind. In exotic cases, we might also see a | 
|  | 163 | // top-level ExprWithCleanups. Ignore them either way. | 
| Bill Wendling | 7c44da2 | 2018-10-31 03:48:47 +0000 | [diff] [blame] | 164 | if (const auto *FE = dyn_cast<FullExpr>(E)) | 
|  | 165 | E = FE->getSubExpr()->IgnoreParens(); | 
| George Burgess IV | 4763876 | 2018-03-07 04:52:34 +0000 | [diff] [blame] | 166 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 167 | if (const auto *Cast = dyn_cast<CastExpr>(E)) | 
|  | 168 | E = Cast->getSubExpr()->IgnoreParens(); | 
|  | 169 |  | 
|  | 170 | if (const auto *CE = dyn_cast<CallExpr>(E)) | 
|  | 171 | return getAllocSizeAttr(CE) ? CE : nullptr; | 
|  | 172 | return nullptr; | 
|  | 173 | } | 
|  | 174 |  | 
|  | 175 | /// Determines whether or not the given Base contains a call to a function | 
|  | 176 | /// with the alloc_size attribute. | 
|  | 177 | static bool isBaseAnAllocSizeCall(APValue::LValueBase Base) { | 
|  | 178 | const auto *E = Base.dyn_cast<const Expr *>(); | 
|  | 179 | return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E); | 
|  | 180 | } | 
|  | 181 |  | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 182 | /// The bound to claim that an array of unknown bound has. | 
|  | 183 | /// The value in MostDerivedArraySize is undefined in this case. So, set it | 
|  | 184 | /// to an arbitrary value that's likely to loudly break things if it's used. | 
|  | 185 | static const uint64_t AssumedSizeForUnsizedArray = | 
|  | 186 | std::numeric_limits<uint64_t>::max() / 2; | 
|  | 187 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 188 | /// Determines if an LValue with the given LValueBase will have an unsized | 
|  | 189 | /// array in its designator. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 190 | /// Find the path length and type of the most-derived subobject in the given | 
|  | 191 | /// path, and find the size of the containing array, if any. | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 192 | static unsigned | 
|  | 193 | findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base, | 
|  | 194 | ArrayRef<APValue::LValuePathEntry> Path, | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 195 | uint64_t &ArraySize, QualType &Type, bool &IsArray, | 
|  | 196 | bool &FirstEntryIsUnsizedArray) { | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 197 | // This only accepts LValueBases from APValues, and APValues don't support | 
|  | 198 | // arrays that lack size info. | 
|  | 199 | assert(!isBaseAnAllocSizeCall(Base) && | 
|  | 200 | "Unsized arrays shouldn't appear here"); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 201 | unsigned MostDerivedLength = 0; | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 202 | Type = getType(Base); | 
|  | 203 |  | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 204 | for (unsigned I = 0, N = Path.size(); I != N; ++I) { | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 205 | if (Type->isArrayType()) { | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 206 | const ArrayType *AT = Ctx.getAsArrayType(Type); | 
|  | 207 | Type = AT->getElementType(); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 208 | MostDerivedLength = I + 1; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 209 | IsArray = true; | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 210 |  | 
|  | 211 | if (auto *CAT = dyn_cast<ConstantArrayType>(AT)) { | 
|  | 212 | ArraySize = CAT->getSize().getZExtValue(); | 
|  | 213 | } else { | 
|  | 214 | assert(I == 0 && "unexpected unsized array designator"); | 
|  | 215 | FirstEntryIsUnsizedArray = true; | 
|  | 216 | ArraySize = AssumedSizeForUnsizedArray; | 
|  | 217 | } | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 218 | } else if (Type->isAnyComplexType()) { | 
|  | 219 | const ComplexType *CT = Type->castAs<ComplexType>(); | 
|  | 220 | Type = CT->getElementType(); | 
|  | 221 | ArraySize = 2; | 
|  | 222 | MostDerivedLength = I + 1; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 223 | IsArray = true; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 224 | } else if (const FieldDecl *FD = getAsField(Path[I])) { | 
|  | 225 | Type = FD->getType(); | 
|  | 226 | ArraySize = 0; | 
|  | 227 | MostDerivedLength = I + 1; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 228 | IsArray = false; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 229 | } else { | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 230 | // Path[I] describes a base class. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 231 | ArraySize = 0; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 232 | IsArray = false; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 233 | } | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 234 | } | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 235 | return MostDerivedLength; | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 236 | } | 
|  | 237 |  | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 238 | /// A path from a glvalue to a subobject of that glvalue. | 
|  | 239 | struct SubobjectDesignator { | 
|  | 240 | /// True if the subobject was named in a manner not supported by C++11. Such | 
|  | 241 | /// lvalues can still be folded, but they are not core constant expressions | 
|  | 242 | /// and we cannot perform lvalue-to-rvalue conversions on them. | 
| Akira Hatanaka | 3a94477 | 2016-06-30 00:07:17 +0000 | [diff] [blame] | 243 | unsigned Invalid : 1; | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 244 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 245 | /// Is this a pointer one past the end of an object? | 
| Akira Hatanaka | 3a94477 | 2016-06-30 00:07:17 +0000 | [diff] [blame] | 246 | unsigned IsOnePastTheEnd : 1; | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 247 |  | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 248 | /// Indicator of whether the first entry is an unsized array. | 
|  | 249 | unsigned FirstEntryIsAnUnsizedArray : 1; | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 250 |  | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 251 | /// Indicator of whether the most-derived object is an array element. | 
| Akira Hatanaka | 3a94477 | 2016-06-30 00:07:17 +0000 | [diff] [blame] | 252 | unsigned MostDerivedIsArrayElement : 1; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 253 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 254 | /// The length of the path to the most-derived object of which this is a | 
|  | 255 | /// subobject. | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 256 | unsigned MostDerivedPathLength : 28; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 257 |  | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 258 | /// The size of the array of which the most-derived object is an element. | 
|  | 259 | /// This will always be 0 if the most-derived object is not an array | 
|  | 260 | /// element. 0 is not an indicator of whether or not the most-derived object | 
|  | 261 | /// is an array, however, because 0-length arrays are allowed. | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 262 | /// | 
|  | 263 | /// If the current array is an unsized array, the value of this is | 
|  | 264 | /// undefined. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 265 | uint64_t MostDerivedArraySize; | 
|  | 266 |  | 
|  | 267 | /// The type of the most derived object referred to by this address. | 
|  | 268 | QualType MostDerivedType; | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 269 |  | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 270 | typedef APValue::LValuePathEntry PathEntry; | 
|  | 271 |  | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 272 | /// The entries on the path from the glvalue to the designated subobject. | 
|  | 273 | SmallVector<PathEntry, 8> Entries; | 
|  | 274 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 275 | SubobjectDesignator() : Invalid(true) {} | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 276 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 277 | explicit SubobjectDesignator(QualType T) | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 278 | : Invalid(false), IsOnePastTheEnd(false), | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 279 | FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 280 | MostDerivedPathLength(0), MostDerivedArraySize(0), | 
|  | 281 | MostDerivedType(T) {} | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 282 |  | 
|  | 283 | SubobjectDesignator(ASTContext &Ctx, const APValue &V) | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 284 | : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false), | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 285 | FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 286 | MostDerivedPathLength(0), MostDerivedArraySize(0) { | 
|  | 287 | assert(V.isLValue() && "Non-LValue used to make an LValue designator?"); | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 288 | if (!Invalid) { | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 289 | IsOnePastTheEnd = V.isLValueOnePastTheEnd(); | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 290 | ArrayRef<PathEntry> VEntries = V.getLValuePath(); | 
|  | 291 | Entries.insert(Entries.end(), VEntries.begin(), VEntries.end()); | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 292 | if (V.getLValueBase()) { | 
|  | 293 | bool IsArray = false; | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 294 | bool FirstIsUnsizedArray = false; | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 295 | MostDerivedPathLength = findMostDerivedSubobject( | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 296 | Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize, | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 297 | MostDerivedType, IsArray, FirstIsUnsizedArray); | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 298 | MostDerivedIsArrayElement = IsArray; | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 299 | FirstEntryIsAnUnsizedArray = FirstIsUnsizedArray; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 300 | } | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 301 | } | 
|  | 302 | } | 
|  | 303 |  | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 304 | void truncate(ASTContext &Ctx, APValue::LValueBase Base, | 
|  | 305 | unsigned NewLength) { | 
|  | 306 | if (Invalid) | 
|  | 307 | return; | 
|  | 308 |  | 
|  | 309 | assert(Base && "cannot truncate path for null pointer"); | 
|  | 310 | assert(NewLength <= Entries.size() && "not a truncation"); | 
|  | 311 |  | 
|  | 312 | if (NewLength == Entries.size()) | 
|  | 313 | return; | 
|  | 314 | Entries.resize(NewLength); | 
|  | 315 |  | 
|  | 316 | bool IsArray = false; | 
|  | 317 | bool FirstIsUnsizedArray = false; | 
|  | 318 | MostDerivedPathLength = findMostDerivedSubobject( | 
|  | 319 | Ctx, Base, Entries, MostDerivedArraySize, MostDerivedType, IsArray, | 
|  | 320 | FirstIsUnsizedArray); | 
|  | 321 | MostDerivedIsArrayElement = IsArray; | 
|  | 322 | FirstEntryIsAnUnsizedArray = FirstIsUnsizedArray; | 
|  | 323 | } | 
|  | 324 |  | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 325 | void setInvalid() { | 
|  | 326 | Invalid = true; | 
|  | 327 | Entries.clear(); | 
|  | 328 | } | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 329 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 330 | /// Determine whether the most derived subobject is an array without a | 
|  | 331 | /// known bound. | 
|  | 332 | bool isMostDerivedAnUnsizedArray() const { | 
|  | 333 | assert(!Invalid && "Calling this makes no sense on invalid designators"); | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 334 | return Entries.size() == 1 && FirstEntryIsAnUnsizedArray; | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 335 | } | 
|  | 336 |  | 
|  | 337 | /// Determine what the most derived array's size is. Results in an assertion | 
|  | 338 | /// failure if the most derived array lacks a size. | 
|  | 339 | uint64_t getMostDerivedArraySize() const { | 
|  | 340 | assert(!isMostDerivedAnUnsizedArray() && "Unsized array has no size"); | 
|  | 341 | return MostDerivedArraySize; | 
|  | 342 | } | 
|  | 343 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 344 | /// Determine whether this is a one-past-the-end pointer. | 
|  | 345 | bool isOnePastTheEnd() const { | 
| Richard Smith | 33b44ab | 2014-07-23 23:50:25 +0000 | [diff] [blame] | 346 | assert(!Invalid); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 347 | if (IsOnePastTheEnd) | 
|  | 348 | return true; | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 349 | if (!isMostDerivedAnUnsizedArray() && MostDerivedIsArrayElement && | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 350 | Entries[MostDerivedPathLength - 1].getAsArrayIndex() == | 
|  | 351 | MostDerivedArraySize) | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 352 | return true; | 
|  | 353 | return false; | 
|  | 354 | } | 
|  | 355 |  | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 356 | /// Get the range of valid index adjustments in the form | 
|  | 357 | ///   {maximum value that can be subtracted from this pointer, | 
|  | 358 | ///    maximum value that can be added to this pointer} | 
|  | 359 | std::pair<uint64_t, uint64_t> validIndexAdjustments() { | 
|  | 360 | if (Invalid || isMostDerivedAnUnsizedArray()) | 
|  | 361 | return {0, 0}; | 
|  | 362 |  | 
|  | 363 | // [expr.add]p4: For the purposes of these operators, a pointer to a | 
|  | 364 | // nonarray object behaves the same as a pointer to the first element of | 
|  | 365 | // an array of length one with the type of the object as its element type. | 
|  | 366 | bool IsArray = MostDerivedPathLength == Entries.size() && | 
|  | 367 | MostDerivedIsArrayElement; | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 368 | uint64_t ArrayIndex = IsArray ? Entries.back().getAsArrayIndex() | 
|  | 369 | : (uint64_t)IsOnePastTheEnd; | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 370 | uint64_t ArraySize = | 
|  | 371 | IsArray ? getMostDerivedArraySize() : (uint64_t)1; | 
|  | 372 | return {ArrayIndex, ArraySize - ArrayIndex}; | 
|  | 373 | } | 
|  | 374 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 375 | /// Check that this refers to a valid subobject. | 
|  | 376 | bool isValidSubobject() const { | 
|  | 377 | if (Invalid) | 
|  | 378 | return false; | 
|  | 379 | return !isOnePastTheEnd(); | 
|  | 380 | } | 
|  | 381 | /// Check that this refers to a valid subobject, and if not, produce a | 
|  | 382 | /// relevant diagnostic and set the designator as invalid. | 
|  | 383 | bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK); | 
|  | 384 |  | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 385 | /// Get the type of the designated object. | 
|  | 386 | QualType getType(ASTContext &Ctx) const { | 
|  | 387 | assert(!Invalid && "invalid designator has no subobject type"); | 
|  | 388 | return MostDerivedPathLength == Entries.size() | 
|  | 389 | ? MostDerivedType | 
|  | 390 | : Ctx.getRecordType(getAsBaseClass(Entries.back())); | 
|  | 391 | } | 
|  | 392 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 393 | /// Update this designator to refer to the first element within this array. | 
|  | 394 | void addArrayUnchecked(const ConstantArrayType *CAT) { | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 395 | Entries.push_back(PathEntry::ArrayIndex(0)); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 396 |  | 
|  | 397 | // This is a most-derived object. | 
|  | 398 | MostDerivedType = CAT->getElementType(); | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 399 | MostDerivedIsArrayElement = true; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 400 | MostDerivedArraySize = CAT->getSize().getZExtValue(); | 
|  | 401 | MostDerivedPathLength = Entries.size(); | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 402 | } | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 403 | /// Update this designator to refer to the first element within the array of | 
|  | 404 | /// elements of type T. This is an array of unknown size. | 
|  | 405 | void addUnsizedArrayUnchecked(QualType ElemTy) { | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 406 | Entries.push_back(PathEntry::ArrayIndex(0)); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 407 |  | 
|  | 408 | MostDerivedType = ElemTy; | 
|  | 409 | MostDerivedIsArrayElement = true; | 
|  | 410 | // The value in MostDerivedArraySize is undefined in this case. So, set it | 
|  | 411 | // to an arbitrary value that's likely to loudly break things if it's | 
|  | 412 | // used. | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 413 | MostDerivedArraySize = AssumedSizeForUnsizedArray; | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 414 | MostDerivedPathLength = Entries.size(); | 
|  | 415 | } | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 416 | /// Update this designator to refer to the given base or member of this | 
|  | 417 | /// object. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 418 | void addDeclUnchecked(const Decl *D, bool Virtual = false) { | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 419 | Entries.push_back(APValue::BaseOrMemberType(D, Virtual)); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 420 |  | 
|  | 421 | // If this isn't a base class, it's a new most-derived object. | 
|  | 422 | if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) { | 
|  | 423 | MostDerivedType = FD->getType(); | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 424 | MostDerivedIsArrayElement = false; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 425 | MostDerivedArraySize = 0; | 
|  | 426 | MostDerivedPathLength = Entries.size(); | 
|  | 427 | } | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 428 | } | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 429 | /// Update this designator to refer to the given complex component. | 
|  | 430 | void addComplexUnchecked(QualType EltTy, bool Imag) { | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 431 | Entries.push_back(PathEntry::ArrayIndex(Imag)); | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 432 |  | 
|  | 433 | // This is technically a most-derived object, though in practice this | 
|  | 434 | // is unlikely to matter. | 
|  | 435 | MostDerivedType = EltTy; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 436 | MostDerivedIsArrayElement = true; | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 437 | MostDerivedArraySize = 2; | 
|  | 438 | MostDerivedPathLength = Entries.size(); | 
|  | 439 | } | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 440 | void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E); | 
| Benjamin Kramer | f6021ec | 2017-03-21 21:35:04 +0000 | [diff] [blame] | 441 | void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, | 
|  | 442 | const APSInt &N); | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 443 | /// Add N to the address of this subobject. | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 444 | void adjustIndex(EvalInfo &Info, const Expr *E, APSInt N) { | 
|  | 445 | if (Invalid || !N) return; | 
|  | 446 | uint64_t TruncatedN = N.extOrTrunc(64).getZExtValue(); | 
|  | 447 | if (isMostDerivedAnUnsizedArray()) { | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 448 | diagnoseUnsizedArrayPointerArithmetic(Info, E); | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 449 | // Can't verify -- trust that the user is doing the right thing (or if | 
|  | 450 | // not, trust that the caller will catch the bad behavior). | 
|  | 451 | // FIXME: Should we reject if this overflows, at least? | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 452 | Entries.back() = PathEntry::ArrayIndex( | 
|  | 453 | Entries.back().getAsArrayIndex() + TruncatedN); | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 454 | return; | 
|  | 455 | } | 
|  | 456 |  | 
|  | 457 | // [expr.add]p4: For the purposes of these operators, a pointer to a | 
|  | 458 | // nonarray object behaves the same as a pointer to the first element of | 
|  | 459 | // an array of length one with the type of the object as its element type. | 
|  | 460 | bool IsArray = MostDerivedPathLength == Entries.size() && | 
|  | 461 | MostDerivedIsArrayElement; | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 462 | uint64_t ArrayIndex = IsArray ? Entries.back().getAsArrayIndex() | 
|  | 463 | : (uint64_t)IsOnePastTheEnd; | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 464 | uint64_t ArraySize = | 
|  | 465 | IsArray ? getMostDerivedArraySize() : (uint64_t)1; | 
|  | 466 |  | 
|  | 467 | if (N < -(int64_t)ArrayIndex || N > ArraySize - ArrayIndex) { | 
|  | 468 | // Calculate the actual index in a wide enough type, so we can include | 
|  | 469 | // it in the note. | 
|  | 470 | N = N.extend(std::max<unsigned>(N.getBitWidth() + 1, 65)); | 
|  | 471 | (llvm::APInt&)N += ArrayIndex; | 
|  | 472 | assert(N.ugt(ArraySize) && "bounds check failed for in-bounds index"); | 
|  | 473 | diagnosePointerArithmetic(Info, E, N); | 
|  | 474 | setInvalid(); | 
|  | 475 | return; | 
|  | 476 | } | 
|  | 477 |  | 
|  | 478 | ArrayIndex += TruncatedN; | 
|  | 479 | assert(ArrayIndex <= ArraySize && | 
|  | 480 | "bounds check succeeded for out-of-bounds index"); | 
|  | 481 |  | 
|  | 482 | if (IsArray) | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 483 | Entries.back() = PathEntry::ArrayIndex(ArrayIndex); | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 484 | else | 
|  | 485 | IsOnePastTheEnd = (ArrayIndex != 0); | 
|  | 486 | } | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 487 | }; | 
|  | 488 |  | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 489 | /// A stack frame in the constexpr call stack. | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 490 | class CallStackFrame : public interp::Frame { | 
|  | 491 | public: | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 492 | EvalInfo &Info; | 
|  | 493 |  | 
|  | 494 | /// Parent - The caller of this stack frame. | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 495 | CallStackFrame *Caller; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 496 |  | 
| Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 497 | /// Callee - The function which was called. | 
|  | 498 | const FunctionDecl *Callee; | 
|  | 499 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 500 | /// This - The binding for the this pointer in this call, if any. | 
|  | 501 | const LValue *This; | 
|  | 502 |  | 
| Nick Lewycky | e2b2caa | 2013-09-22 10:07:22 +0000 | [diff] [blame] | 503 | /// Arguments - Parameter bindings for this function call, indexed by | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 504 | /// parameters' function scope indices. | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 505 | APValue *Arguments; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 506 |  | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 507 | /// Source location information about the default argument or default | 
|  | 508 | /// initializer expression we're evaluating, if any. | 
|  | 509 | CurrentSourceLocExprScope CurSourceLocExprScope; | 
|  | 510 |  | 
| Eli Friedman | 4830ec8 | 2012-06-25 21:21:08 +0000 | [diff] [blame] | 511 | // Note that we intentionally use std::map here so that references to | 
|  | 512 | // values are stable. | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 513 | typedef std::pair<const void *, unsigned> MapKeyTy; | 
|  | 514 | typedef std::map<MapKeyTy, APValue> MapTy; | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 515 | /// Temporaries - Temporary lvalues materialized within this stack frame. | 
|  | 516 | MapTy Temporaries; | 
|  | 517 |  | 
| Alexander Shaposhnikov | fbcf29b | 2016-09-19 15:57:29 +0000 | [diff] [blame] | 518 | /// CallLoc - The location of the call expression for this call. | 
|  | 519 | SourceLocation CallLoc; | 
|  | 520 |  | 
|  | 521 | /// Index - The call index of this call. | 
|  | 522 | unsigned Index; | 
|  | 523 |  | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 524 | /// The stack of integers for tracking version numbers for temporaries. | 
|  | 525 | SmallVector<unsigned, 2> TempVersionStack = {1}; | 
|  | 526 | unsigned CurTempVersion = TempVersionStack.back(); | 
|  | 527 |  | 
|  | 528 | unsigned getTempVersion() const { return TempVersionStack.back(); } | 
|  | 529 |  | 
|  | 530 | void pushTempVersion() { | 
|  | 531 | TempVersionStack.push_back(++CurTempVersion); | 
|  | 532 | } | 
|  | 533 |  | 
|  | 534 | void popTempVersion() { | 
|  | 535 | TempVersionStack.pop_back(); | 
|  | 536 | } | 
|  | 537 |  | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 538 | // FIXME: Adding this to every 'CallStackFrame' may have a nontrivial impact | 
| Raphael Isemann | b23ccec | 2018-12-10 12:37:46 +0000 | [diff] [blame] | 539 | // on the overall stack usage of deeply-recursing constexpr evaluations. | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 540 | // (We should cache this map rather than recomputing it repeatedly.) | 
|  | 541 | // But let's try this and see how it goes; we can look into caching the map | 
|  | 542 | // as a later change. | 
|  | 543 |  | 
|  | 544 | /// LambdaCaptureFields - Mapping from captured variables/this to | 
|  | 545 | /// corresponding data members in the closure class. | 
|  | 546 | llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; | 
|  | 547 | FieldDecl *LambdaThisCaptureField; | 
|  | 548 |  | 
| Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 549 | CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, | 
|  | 550 | const FunctionDecl *Callee, const LValue *This, | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 551 | APValue *Arguments); | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 552 | ~CallStackFrame(); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 553 |  | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 554 | // Return the temporary for Key whose version number is Version. | 
|  | 555 | APValue *getTemporary(const void *Key, unsigned Version) { | 
|  | 556 | MapKeyTy KV(Key, Version); | 
|  | 557 | auto LB = Temporaries.lower_bound(KV); | 
|  | 558 | if (LB != Temporaries.end() && LB->first == KV) | 
|  | 559 | return &LB->second; | 
|  | 560 | // Pair (Key,Version) wasn't found in the map. Check that no elements | 
|  | 561 | // in the map have 'Key' as their key. | 
|  | 562 | assert((LB == Temporaries.end() || LB->first.first != Key) && | 
|  | 563 | (LB == Temporaries.begin() || std::prev(LB)->first.first != Key) && | 
|  | 564 | "Element with key 'Key' found in map"); | 
|  | 565 | return nullptr; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 566 | } | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 567 |  | 
|  | 568 | // Return the current temporary for Key in the map. | 
|  | 569 | APValue *getCurrentTemporary(const void *Key) { | 
|  | 570 | auto UB = Temporaries.upper_bound(MapKeyTy(Key, UINT_MAX)); | 
|  | 571 | if (UB != Temporaries.begin() && std::prev(UB)->first.first == Key) | 
|  | 572 | return &std::prev(UB)->second; | 
|  | 573 | return nullptr; | 
|  | 574 | } | 
|  | 575 |  | 
|  | 576 | // Return the version number of the current temporary for Key. | 
|  | 577 | unsigned getCurrentTemporaryVersion(const void *Key) const { | 
|  | 578 | auto UB = Temporaries.upper_bound(MapKeyTy(Key, UINT_MAX)); | 
|  | 579 | if (UB != Temporaries.begin() && std::prev(UB)->first.first == Key) | 
|  | 580 | return std::prev(UB)->first.second; | 
|  | 581 | return 0; | 
|  | 582 | } | 
|  | 583 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 584 | /// Allocate storage for an object of type T in this stack frame. | 
|  | 585 | /// Populates LV with a handle to the created object. Key identifies | 
|  | 586 | /// the temporary within the stack frame, and must not be reused without | 
|  | 587 | /// bumping the temporary version number. | 
|  | 588 | template<typename KeyT> | 
|  | 589 | APValue &createTemporary(const KeyT *Key, QualType T, | 
|  | 590 | bool IsLifetimeExtended, LValue &LV); | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 591 |  | 
|  | 592 | void describe(llvm::raw_ostream &OS) override; | 
|  | 593 |  | 
|  | 594 | Frame *getCaller() const override { return Caller; } | 
|  | 595 | SourceLocation getCallLocation() const override { return CallLoc; } | 
|  | 596 | const FunctionDecl *getCallee() const override { return Callee; } | 
| Richard Smith | b542602 | 2019-10-03 00:39:35 +0000 | [diff] [blame] | 597 |  | 
|  | 598 | bool isStdFunction() const { | 
|  | 599 | for (const DeclContext *DC = Callee; DC; DC = DC->getParent()) | 
|  | 600 | if (DC->isStdNamespace()) | 
|  | 601 | return true; | 
|  | 602 | return false; | 
|  | 603 | } | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 604 | }; | 
|  | 605 |  | 
| Richard Smith | 852c9db | 2013-04-20 22:23:05 +0000 | [diff] [blame] | 606 | /// Temporarily override 'this'. | 
|  | 607 | class ThisOverrideRAII { | 
|  | 608 | public: | 
|  | 609 | ThisOverrideRAII(CallStackFrame &Frame, const LValue *NewThis, bool Enable) | 
|  | 610 | : Frame(Frame), OldThis(Frame.This) { | 
|  | 611 | if (Enable) | 
|  | 612 | Frame.This = NewThis; | 
|  | 613 | } | 
|  | 614 | ~ThisOverrideRAII() { | 
|  | 615 | Frame.This = OldThis; | 
|  | 616 | } | 
|  | 617 | private: | 
|  | 618 | CallStackFrame &Frame; | 
|  | 619 | const LValue *OldThis; | 
|  | 620 | }; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 621 | } | 
| Richard Smith | 852c9db | 2013-04-20 22:23:05 +0000 | [diff] [blame] | 622 |  | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 623 | static bool HandleDestruction(EvalInfo &Info, const Expr *E, | 
|  | 624 | const LValue &This, QualType ThisType); | 
|  | 625 | static bool HandleDestruction(EvalInfo &Info, SourceLocation Loc, | 
|  | 626 | APValue::LValueBase LVBase, APValue &Value, | 
|  | 627 | QualType T); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 628 |  | 
|  | 629 | namespace { | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 630 | /// A cleanup, and a flag indicating whether it is lifetime-extended. | 
|  | 631 | class Cleanup { | 
|  | 632 | llvm::PointerIntPair<APValue*, 1, bool> Value; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 633 | APValue::LValueBase Base; | 
|  | 634 | QualType T; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 635 |  | 
|  | 636 | public: | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 637 | Cleanup(APValue *Val, APValue::LValueBase Base, QualType T, | 
|  | 638 | bool IsLifetimeExtended) | 
|  | 639 | : Value(Val, IsLifetimeExtended), Base(Base), T(T) {} | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 640 |  | 
|  | 641 | bool isLifetimeExtended() const { return Value.getInt(); } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 642 | bool endLifetime(EvalInfo &Info, bool RunDestructors) { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 643 | if (RunDestructors) { | 
|  | 644 | SourceLocation Loc; | 
|  | 645 | if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) | 
|  | 646 | Loc = VD->getLocation(); | 
|  | 647 | else if (const Expr *E = Base.dyn_cast<const Expr*>()) | 
|  | 648 | Loc = E->getExprLoc(); | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 649 | return HandleDestruction(Info, Loc, Base, *Value.getPointer(), T); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 650 | } | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 651 | *Value.getPointer() = APValue(); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 652 | return true; | 
|  | 653 | } | 
|  | 654 |  | 
|  | 655 | bool hasSideEffect() { | 
|  | 656 | return T.isDestructedType(); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 657 | } | 
|  | 658 | }; | 
|  | 659 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 660 | /// A reference to an object whose construction we are currently evaluating. | 
|  | 661 | struct ObjectUnderConstruction { | 
|  | 662 | APValue::LValueBase Base; | 
|  | 663 | ArrayRef<APValue::LValuePathEntry> Path; | 
|  | 664 | friend bool operator==(const ObjectUnderConstruction &LHS, | 
|  | 665 | const ObjectUnderConstruction &RHS) { | 
|  | 666 | return LHS.Base == RHS.Base && LHS.Path == RHS.Path; | 
|  | 667 | } | 
|  | 668 | friend llvm::hash_code hash_value(const ObjectUnderConstruction &Obj) { | 
|  | 669 | return llvm::hash_combine(Obj.Base, Obj.Path); | 
|  | 670 | } | 
|  | 671 | }; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 672 | enum class ConstructionPhase { | 
|  | 673 | None, | 
|  | 674 | Bases, | 
|  | 675 | AfterBases, | 
|  | 676 | Destroying, | 
|  | 677 | DestroyingBases | 
|  | 678 | }; | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 679 | } | 
|  | 680 |  | 
|  | 681 | namespace llvm { | 
|  | 682 | template<> struct DenseMapInfo<ObjectUnderConstruction> { | 
|  | 683 | using Base = DenseMapInfo<APValue::LValueBase>; | 
|  | 684 | static ObjectUnderConstruction getEmptyKey() { | 
|  | 685 | return {Base::getEmptyKey(), {}}; } | 
|  | 686 | static ObjectUnderConstruction getTombstoneKey() { | 
|  | 687 | return {Base::getTombstoneKey(), {}}; | 
|  | 688 | } | 
|  | 689 | static unsigned getHashValue(const ObjectUnderConstruction &Object) { | 
|  | 690 | return hash_value(Object); | 
|  | 691 | } | 
|  | 692 | static bool isEqual(const ObjectUnderConstruction &LHS, | 
|  | 693 | const ObjectUnderConstruction &RHS) { | 
|  | 694 | return LHS == RHS; | 
|  | 695 | } | 
|  | 696 | }; | 
|  | 697 | } | 
|  | 698 |  | 
|  | 699 | namespace { | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 700 | /// A dynamically-allocated heap object. | 
|  | 701 | struct DynAlloc { | 
|  | 702 | /// The value of this heap-allocated object. | 
|  | 703 | APValue Value; | 
|  | 704 | /// The allocating expression; used for diagnostics. Either a CXXNewExpr | 
|  | 705 | /// or a CallExpr (the latter is for direct calls to operator new inside | 
|  | 706 | /// std::allocator<T>::allocate). | 
|  | 707 | const Expr *AllocExpr = nullptr; | 
|  | 708 |  | 
|  | 709 | enum Kind { | 
|  | 710 | New, | 
|  | 711 | ArrayNew, | 
|  | 712 | StdAllocator | 
|  | 713 | }; | 
|  | 714 |  | 
|  | 715 | /// Get the kind of the allocation. This must match between allocation | 
|  | 716 | /// and deallocation. | 
|  | 717 | Kind getKind() const { | 
|  | 718 | if (auto *NE = dyn_cast<CXXNewExpr>(AllocExpr)) | 
|  | 719 | return NE->isArray() ? ArrayNew : New; | 
|  | 720 | assert(isa<CallExpr>(AllocExpr)); | 
|  | 721 | return StdAllocator; | 
|  | 722 | } | 
|  | 723 | }; | 
|  | 724 |  | 
|  | 725 | struct DynAllocOrder { | 
|  | 726 | bool operator()(DynamicAllocLValue L, DynamicAllocLValue R) const { | 
|  | 727 | return L.getIndex() < R.getIndex(); | 
|  | 728 | } | 
|  | 729 | }; | 
|  | 730 |  | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 731 | /// EvalInfo - This is a private struct used by the evaluator to capture | 
|  | 732 | /// information about a subexpression as it is folded.  It retains information | 
|  | 733 | /// about the AST context, but also maintains information about the folded | 
|  | 734 | /// expression. | 
|  | 735 | /// | 
|  | 736 | /// If an expression could be evaluated, it is still possible it is not a C | 
|  | 737 | /// "integer constant expression" or constant expression.  If not, this struct | 
|  | 738 | /// captures information about how and why not. | 
|  | 739 | /// | 
|  | 740 | /// One bit of information passed *into* the request for constant folding | 
|  | 741 | /// indicates whether the subexpression is "evaluated" or not according to C | 
|  | 742 | /// rules.  For example, the RHS of (0 && foo()) is not evaluated.  We can | 
|  | 743 | /// evaluate the expression regardless of what the RHS is, but C only allows | 
|  | 744 | /// certain things in certain situations. | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 745 | class EvalInfo : public interp::State { | 
|  | 746 | public: | 
| Richard Smith | 92b1ce0 | 2011-12-12 09:28:41 +0000 | [diff] [blame] | 747 | ASTContext &Ctx; | 
| Argyrios Kyrtzidis | 91d0098 | 2012-02-27 20:21:34 +0000 | [diff] [blame] | 748 |  | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 749 | /// EvalStatus - Contains information about the evaluation. | 
|  | 750 | Expr::EvalStatus &EvalStatus; | 
|  | 751 |  | 
|  | 752 | /// CurrentCall - The top of the constexpr call stack. | 
|  | 753 | CallStackFrame *CurrentCall; | 
|  | 754 |  | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 755 | /// CallStackDepth - The number of calls in the call stack right now. | 
|  | 756 | unsigned CallStackDepth; | 
|  | 757 |  | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 758 | /// NextCallIndex - The next call index to assign. | 
|  | 759 | unsigned NextCallIndex; | 
|  | 760 |  | 
| Richard Smith | a3d3bd2 | 2013-05-08 02:12:03 +0000 | [diff] [blame] | 761 | /// StepsLeft - The remaining number of evaluation steps we're permitted | 
|  | 762 | /// to perform. This is essentially a limit for the number of statements | 
|  | 763 | /// we will evaluate. | 
|  | 764 | unsigned StepsLeft; | 
|  | 765 |  | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 766 | /// Enable the experimental new constant interpreter. If an expression is | 
|  | 767 | /// not supported by the interpreter, an error is triggered. | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 768 | bool EnableNewConstInterp; | 
|  | 769 |  | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 770 | /// BottomFrame - The frame in which evaluation started. This must be | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 771 | /// initialized after CurrentCall and CallStackDepth. | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 772 | CallStackFrame BottomFrame; | 
|  | 773 |  | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 774 | /// A stack of values whose lifetimes end at the end of some surrounding | 
|  | 775 | /// evaluation frame. | 
|  | 776 | llvm::SmallVector<Cleanup, 16> CleanupStack; | 
|  | 777 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 778 | /// EvaluatingDecl - This is the declaration whose initializer is being | 
|  | 779 | /// evaluated, if any. | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 780 | APValue::LValueBase EvaluatingDecl; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 781 |  | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 782 | enum class EvaluatingDeclKind { | 
|  | 783 | None, | 
|  | 784 | /// We're evaluating the construction of EvaluatingDecl. | 
|  | 785 | Ctor, | 
|  | 786 | /// We're evaluating the destruction of EvaluatingDecl. | 
|  | 787 | Dtor, | 
|  | 788 | }; | 
|  | 789 | EvaluatingDeclKind IsEvaluatingDecl = EvaluatingDeclKind::None; | 
|  | 790 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 791 | /// EvaluatingDeclValue - This is the value being constructed for the | 
|  | 792 | /// declaration whose initializer is being evaluated, if any. | 
|  | 793 | APValue *EvaluatingDeclValue; | 
|  | 794 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 795 | /// Set of objects that are currently being constructed. | 
|  | 796 | llvm::DenseMap<ObjectUnderConstruction, ConstructionPhase> | 
|  | 797 | ObjectsUnderConstruction; | 
| Erik Pilkington | 4292549 | 2017-10-04 00:18:55 +0000 | [diff] [blame] | 798 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 799 | /// Current heap allocations, along with the location where each was | 
|  | 800 | /// allocated. We use std::map here because we need stable addresses | 
|  | 801 | /// for the stored APValues. | 
|  | 802 | std::map<DynamicAllocLValue, DynAlloc, DynAllocOrder> HeapAllocs; | 
|  | 803 |  | 
|  | 804 | /// The number of heap allocations performed so far in this evaluation. | 
|  | 805 | unsigned NumHeapAllocs = 0; | 
|  | 806 |  | 
| Erik Pilkington | 4292549 | 2017-10-04 00:18:55 +0000 | [diff] [blame] | 807 | struct EvaluatingConstructorRAII { | 
|  | 808 | EvalInfo &EI; | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 809 | ObjectUnderConstruction Object; | 
| Erik Pilkington | 4292549 | 2017-10-04 00:18:55 +0000 | [diff] [blame] | 810 | bool DidInsert; | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 811 | EvaluatingConstructorRAII(EvalInfo &EI, ObjectUnderConstruction Object, | 
|  | 812 | bool HasBases) | 
| Erik Pilkington | 4292549 | 2017-10-04 00:18:55 +0000 | [diff] [blame] | 813 | : EI(EI), Object(Object) { | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 814 | DidInsert = | 
|  | 815 | EI.ObjectsUnderConstruction | 
|  | 816 | .insert({Object, HasBases ? ConstructionPhase::Bases | 
|  | 817 | : ConstructionPhase::AfterBases}) | 
|  | 818 | .second; | 
|  | 819 | } | 
|  | 820 | void finishedConstructingBases() { | 
|  | 821 | EI.ObjectsUnderConstruction[Object] = ConstructionPhase::AfterBases; | 
| Erik Pilkington | 4292549 | 2017-10-04 00:18:55 +0000 | [diff] [blame] | 822 | } | 
|  | 823 | ~EvaluatingConstructorRAII() { | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 824 | if (DidInsert) EI.ObjectsUnderConstruction.erase(Object); | 
| Erik Pilkington | 4292549 | 2017-10-04 00:18:55 +0000 | [diff] [blame] | 825 | } | 
|  | 826 | }; | 
|  | 827 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 828 | struct EvaluatingDestructorRAII { | 
|  | 829 | EvalInfo &EI; | 
|  | 830 | ObjectUnderConstruction Object; | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 831 | bool DidInsert; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 832 | EvaluatingDestructorRAII(EvalInfo &EI, ObjectUnderConstruction Object) | 
|  | 833 | : EI(EI), Object(Object) { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 834 | DidInsert = EI.ObjectsUnderConstruction | 
|  | 835 | .insert({Object, ConstructionPhase::Destroying}) | 
|  | 836 | .second; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 837 | } | 
|  | 838 | void startedDestroyingBases() { | 
|  | 839 | EI.ObjectsUnderConstruction[Object] = | 
|  | 840 | ConstructionPhase::DestroyingBases; | 
|  | 841 | } | 
|  | 842 | ~EvaluatingDestructorRAII() { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 843 | if (DidInsert) | 
|  | 844 | EI.ObjectsUnderConstruction.erase(Object); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 845 | } | 
|  | 846 | }; | 
|  | 847 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 848 | ConstructionPhase | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 849 | isEvaluatingCtorDtor(APValue::LValueBase Base, | 
|  | 850 | ArrayRef<APValue::LValuePathEntry> Path) { | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 851 | return ObjectsUnderConstruction.lookup({Base, Path}); | 
| Erik Pilkington | 4292549 | 2017-10-04 00:18:55 +0000 | [diff] [blame] | 852 | } | 
|  | 853 |  | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 854 | /// If we're currently speculatively evaluating, the outermost call stack | 
|  | 855 | /// depth at which we can mutate state, otherwise 0. | 
|  | 856 | unsigned SpeculativeEvaluationDepth = 0; | 
|  | 857 |  | 
| Richard Smith | 410306b | 2016-12-12 02:53:20 +0000 | [diff] [blame] | 858 | /// The current array initialization index, if we're performing array | 
|  | 859 | /// initialization. | 
|  | 860 | uint64_t ArrayInitIndex = -1; | 
|  | 861 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 862 | /// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further | 
|  | 863 | /// notes attached to it will also be stored, otherwise they will not be. | 
|  | 864 | bool HasActiveDiagnostic; | 
|  | 865 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 866 | /// Have we emitted a diagnostic explaining why we couldn't constant | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 867 | /// fold (not just why it's not strictly a constant expression)? | 
|  | 868 | bool HasFoldFailureDiagnostic; | 
|  | 869 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 870 | /// Whether or not we're in a context where the front end requires a | 
|  | 871 | /// constant value. | 
|  | 872 | bool InConstantContext; | 
|  | 873 |  | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 874 | /// Whether we're checking that an expression is a potential constant | 
|  | 875 | /// expression. If so, do not fail on constructs that could become constant | 
|  | 876 | /// later on (such as a use of an undefined global). | 
|  | 877 | bool CheckingPotentialConstantExpression = false; | 
|  | 878 |  | 
|  | 879 | /// Whether we're checking for an expression that has undefined behavior. | 
|  | 880 | /// If so, we will produce warnings if we encounter an operation that is | 
|  | 881 | /// always undefined. | 
|  | 882 | bool CheckingForUndefinedBehavior = false; | 
|  | 883 |  | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 884 | enum EvaluationMode { | 
|  | 885 | /// Evaluate as a constant expression. Stop if we find that the expression | 
|  | 886 | /// is not a constant expression. | 
|  | 887 | EM_ConstantExpression, | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 888 |  | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 889 | /// Evaluate as a constant expression. Stop if we find that the expression | 
|  | 890 | /// is not a constant expression. Some expressions can be retried in the | 
|  | 891 | /// optimizer if we don't constant fold them here, but in an unevaluated | 
|  | 892 | /// context we try to fold them immediately since the optimizer never | 
|  | 893 | /// gets a chance to look at it. | 
|  | 894 | EM_ConstantExpressionUnevaluated, | 
|  | 895 |  | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 896 | /// Fold the expression to a constant. Stop if we hit a side-effect that | 
|  | 897 | /// we can't model. | 
|  | 898 | EM_ConstantFold, | 
|  | 899 |  | 
|  | 900 | /// Evaluate in any way we know how. Don't worry about side-effects that | 
|  | 901 | /// can't be modeled. | 
|  | 902 | EM_IgnoreSideEffects, | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 903 | } EvalMode; | 
|  | 904 |  | 
|  | 905 | /// Are we checking whether the expression is a potential constant | 
|  | 906 | /// expression? | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 907 | bool checkingPotentialConstantExpression() const override  { | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 908 | return CheckingPotentialConstantExpression; | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 909 | } | 
|  | 910 |  | 
|  | 911 | /// Are we checking an expression for overflow? | 
|  | 912 | // FIXME: We should check for any kind of undefined or suspicious behavior | 
|  | 913 | // in such constructs, not just overflow. | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 914 | bool checkingForUndefinedBehavior() const override { | 
|  | 915 | return CheckingForUndefinedBehavior; | 
|  | 916 | } | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 917 |  | 
|  | 918 | EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 919 | : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr), | 
|  | 920 | CallStackDepth(0), NextCallIndex(1), | 
| Yaxun (Sam) Liu | ded2490 | 2019-11-26 13:13:47 -0500 | [diff] [blame] | 921 | StepsLeft(C.getLangOpts().ConstexprStepLimit), | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 922 | EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp), | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 923 | BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), | 
|  | 924 | EvaluatingDecl((const ValueDecl *)nullptr), | 
|  | 925 | EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), | 
|  | 926 | HasFoldFailureDiagnostic(false), InConstantContext(false), | 
|  | 927 | EvalMode(Mode) {} | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 928 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 929 | ~EvalInfo() { | 
|  | 930 | discardCleanups(); | 
|  | 931 | } | 
|  | 932 |  | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 933 | void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value, | 
|  | 934 | EvaluatingDeclKind EDK = EvaluatingDeclKind::Ctor) { | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 935 | EvaluatingDecl = Base; | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 936 | IsEvaluatingDecl = EDK; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 937 | EvaluatingDeclValue = &Value; | 
|  | 938 | } | 
|  | 939 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 940 | bool CheckCallLimit(SourceLocation Loc) { | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 941 | // Don't perform any constexpr calls (other than the call we're checking) | 
|  | 942 | // when checking a potential constant expression. | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 943 | if (checkingPotentialConstantExpression() && CallStackDepth > 1) | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 944 | return false; | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 945 | if (NextCallIndex == 0) { | 
|  | 946 | // NextCallIndex has wrapped around. | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 947 | FFDiag(Loc, diag::note_constexpr_call_limit_exceeded); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 948 | return false; | 
|  | 949 | } | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 950 | if (CallStackDepth <= getLangOpts().ConstexprCallDepth) | 
|  | 951 | return true; | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 952 | FFDiag(Loc, diag::note_constexpr_depth_limit_exceeded) | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 953 | << getLangOpts().ConstexprCallDepth; | 
|  | 954 | return false; | 
| Richard Smith | 9a56882 | 2011-11-21 19:36:32 +0000 | [diff] [blame] | 955 | } | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 956 |  | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 957 | std::pair<CallStackFrame *, unsigned> | 
|  | 958 | getCallFrameAndDepth(unsigned CallIndex) { | 
|  | 959 | assert(CallIndex && "no call index in getCallFrameAndDepth"); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 960 | // We will eventually hit BottomFrame, which has Index 1, so Frame can't | 
|  | 961 | // be null in this loop. | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 962 | unsigned Depth = CallStackDepth; | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 963 | CallStackFrame *Frame = CurrentCall; | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 964 | while (Frame->Index > CallIndex) { | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 965 | Frame = Frame->Caller; | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 966 | --Depth; | 
|  | 967 | } | 
|  | 968 | if (Frame->Index == CallIndex) | 
|  | 969 | return {Frame, Depth}; | 
|  | 970 | return {nullptr, 0}; | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 971 | } | 
|  | 972 |  | 
| Richard Smith | a3d3bd2 | 2013-05-08 02:12:03 +0000 | [diff] [blame] | 973 | bool nextStep(const Stmt *S) { | 
|  | 974 | if (!StepsLeft) { | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 975 | FFDiag(S->getBeginLoc(), diag::note_constexpr_step_limit_exceeded); | 
| Richard Smith | a3d3bd2 | 2013-05-08 02:12:03 +0000 | [diff] [blame] | 976 | return false; | 
|  | 977 | } | 
|  | 978 | --StepsLeft; | 
|  | 979 | return true; | 
|  | 980 | } | 
|  | 981 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 982 | APValue *createHeapAlloc(const Expr *E, QualType T, LValue &LV); | 
|  | 983 |  | 
|  | 984 | Optional<DynAlloc*> lookupDynamicAlloc(DynamicAllocLValue DA) { | 
|  | 985 | Optional<DynAlloc*> Result; | 
|  | 986 | auto It = HeapAllocs.find(DA); | 
|  | 987 | if (It != HeapAllocs.end()) | 
|  | 988 | Result = &It->second; | 
|  | 989 | return Result; | 
|  | 990 | } | 
|  | 991 |  | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 992 | /// Information about a stack frame for std::allocator<T>::[de]allocate. | 
|  | 993 | struct StdAllocatorCaller { | 
|  | 994 | unsigned FrameIndex; | 
|  | 995 | QualType ElemType; | 
|  | 996 | explicit operator bool() const { return FrameIndex != 0; }; | 
|  | 997 | }; | 
|  | 998 |  | 
|  | 999 | StdAllocatorCaller getStdAllocatorCaller(StringRef FnName) const { | 
|  | 1000 | for (const CallStackFrame *Call = CurrentCall; Call != &BottomFrame; | 
|  | 1001 | Call = Call->Caller) { | 
|  | 1002 | const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Call->Callee); | 
|  | 1003 | if (!MD) | 
|  | 1004 | continue; | 
|  | 1005 | const IdentifierInfo *FnII = MD->getIdentifier(); | 
|  | 1006 | if (!FnII || !FnII->isStr(FnName)) | 
|  | 1007 | continue; | 
|  | 1008 |  | 
|  | 1009 | const auto *CTSD = | 
|  | 1010 | dyn_cast<ClassTemplateSpecializationDecl>(MD->getParent()); | 
|  | 1011 | if (!CTSD) | 
|  | 1012 | continue; | 
|  | 1013 |  | 
|  | 1014 | const IdentifierInfo *ClassII = CTSD->getIdentifier(); | 
|  | 1015 | const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); | 
|  | 1016 | if (CTSD->isInStdNamespace() && ClassII && | 
|  | 1017 | ClassII->isStr("allocator") && TAL.size() >= 1 && | 
|  | 1018 | TAL[0].getKind() == TemplateArgument::Type) | 
|  | 1019 | return {Call->Index, TAL[0].getAsType()}; | 
|  | 1020 | } | 
|  | 1021 |  | 
|  | 1022 | return {}; | 
|  | 1023 | } | 
|  | 1024 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1025 | void performLifetimeExtension() { | 
|  | 1026 | // Disable the cleanups for lifetime-extended temporaries. | 
|  | 1027 | CleanupStack.erase( | 
|  | 1028 | std::remove_if(CleanupStack.begin(), CleanupStack.end(), | 
|  | 1029 | [](Cleanup &C) { return C.isLifetimeExtended(); }), | 
|  | 1030 | CleanupStack.end()); | 
|  | 1031 | } | 
|  | 1032 |  | 
|  | 1033 | /// Throw away any remaining cleanups at the end of evaluation. If any | 
|  | 1034 | /// cleanups would have had a side-effect, note that as an unmodeled | 
|  | 1035 | /// side-effect and return false. Otherwise, return true. | 
|  | 1036 | bool discardCleanups() { | 
| Richard Smith | bb06149 | 2019-10-30 13:32:52 -0700 | [diff] [blame] | 1037 | for (Cleanup &C : CleanupStack) { | 
|  | 1038 | if (C.hasSideEffect() && !noteSideEffect()) { | 
|  | 1039 | CleanupStack.clear(); | 
|  | 1040 | return false; | 
|  | 1041 | } | 
|  | 1042 | } | 
|  | 1043 | CleanupStack.clear(); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1044 | return true; | 
|  | 1045 | } | 
|  | 1046 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 1047 | private: | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1048 | interp::Frame *getCurrentFrame() override { return CurrentCall; } | 
|  | 1049 | const interp::Frame *getBottomFrame() const override { return &BottomFrame; } | 
|  | 1050 |  | 
|  | 1051 | bool hasActiveDiagnostic() override { return HasActiveDiagnostic; } | 
|  | 1052 | void setActiveDiagnostic(bool Flag) override { HasActiveDiagnostic = Flag; } | 
|  | 1053 |  | 
|  | 1054 | void setFoldFailureDiagnostic(bool Flag) override { | 
|  | 1055 | HasFoldFailureDiagnostic = Flag; | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 1056 | } | 
|  | 1057 |  | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1058 | Expr::EvalStatus &getEvalStatus() const override { return EvalStatus; } | 
| Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 1059 |  | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1060 | ASTContext &getCtx() const override { return Ctx; } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 1061 |  | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1062 | // If we have a prior diagnostic, it will be noting that the expression | 
|  | 1063 | // isn't a constant expression. This diagnostic is more important, | 
|  | 1064 | // unless we require this evaluation to produce a constant expression. | 
|  | 1065 | // | 
|  | 1066 | // FIXME: We might want to show both diagnostics to the user in | 
|  | 1067 | // EM_ConstantFold mode. | 
|  | 1068 | bool hasPriorDiagnostic() override { | 
|  | 1069 | if (!EvalStatus.Diag->empty()) { | 
|  | 1070 | switch (EvalMode) { | 
|  | 1071 | case EM_ConstantFold: | 
|  | 1072 | case EM_IgnoreSideEffects: | 
|  | 1073 | if (!HasFoldFailureDiagnostic) | 
|  | 1074 | break; | 
|  | 1075 | // We've already failed to fold something. Keep that diagnostic. | 
|  | 1076 | LLVM_FALLTHROUGH; | 
|  | 1077 | case EM_ConstantExpression: | 
|  | 1078 | case EM_ConstantExpressionUnevaluated: | 
|  | 1079 | setActiveDiagnostic(false); | 
|  | 1080 | return true; | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1081 | } | 
| Richard Smith | 92b1ce0 | 2011-12-12 09:28:41 +0000 | [diff] [blame] | 1082 | } | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1083 | return false; | 
| Richard Smith | 92b1ce0 | 2011-12-12 09:28:41 +0000 | [diff] [blame] | 1084 | } | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1085 |  | 
|  | 1086 | unsigned getCallStackDepth() override { return CallStackDepth; } | 
|  | 1087 |  | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 1088 | public: | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1089 | /// Should we continue evaluation after encountering a side-effect that we | 
|  | 1090 | /// couldn't model? | 
|  | 1091 | bool keepEvaluatingAfterSideEffect() { | 
|  | 1092 | switch (EvalMode) { | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1093 | case EM_IgnoreSideEffects: | 
|  | 1094 | return true; | 
|  | 1095 |  | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1096 | case EM_ConstantExpression: | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 1097 | case EM_ConstantExpressionUnevaluated: | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1098 | case EM_ConstantFold: | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 1099 | // By default, assume any side effect might be valid in some other | 
|  | 1100 | // evaluation of this expression from a different context. | 
|  | 1101 | return checkingPotentialConstantExpression() || | 
|  | 1102 | checkingForUndefinedBehavior(); | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1103 | } | 
| Aaron Ballman | f682f53 | 2013-11-06 18:15:02 +0000 | [diff] [blame] | 1104 | llvm_unreachable("Missed EvalMode case"); | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1105 | } | 
|  | 1106 |  | 
|  | 1107 | /// Note that we have had a side-effect, and determine whether we should | 
|  | 1108 | /// keep evaluating. | 
|  | 1109 | bool noteSideEffect() { | 
|  | 1110 | EvalStatus.HasSideEffects = true; | 
|  | 1111 | return keepEvaluatingAfterSideEffect(); | 
|  | 1112 | } | 
|  | 1113 |  | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 1114 | /// Should we continue evaluation after encountering undefined behavior? | 
|  | 1115 | bool keepEvaluatingAfterUndefinedBehavior() { | 
|  | 1116 | switch (EvalMode) { | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 1117 | case EM_IgnoreSideEffects: | 
|  | 1118 | case EM_ConstantFold: | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 1119 | return true; | 
|  | 1120 |  | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 1121 | case EM_ConstantExpression: | 
|  | 1122 | case EM_ConstantExpressionUnevaluated: | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 1123 | return checkingForUndefinedBehavior(); | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 1124 | } | 
|  | 1125 | llvm_unreachable("Missed EvalMode case"); | 
|  | 1126 | } | 
|  | 1127 |  | 
|  | 1128 | /// Note that we hit something that was technically undefined behavior, but | 
|  | 1129 | /// that we can evaluate past it (such as signed overflow or floating-point | 
|  | 1130 | /// division by zero.) | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1131 | bool noteUndefinedBehavior() override { | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 1132 | EvalStatus.HasUndefinedBehavior = true; | 
|  | 1133 | return keepEvaluatingAfterUndefinedBehavior(); | 
|  | 1134 | } | 
|  | 1135 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 1136 | /// Should we continue evaluation as much as possible after encountering a | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1137 | /// construct which can't be reduced to a value? | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1138 | bool keepEvaluatingAfterFailure() const override { | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1139 | if (!StepsLeft) | 
|  | 1140 | return false; | 
|  | 1141 |  | 
|  | 1142 | switch (EvalMode) { | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1143 | case EM_ConstantExpression: | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 1144 | case EM_ConstantExpressionUnevaluated: | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1145 | case EM_ConstantFold: | 
|  | 1146 | case EM_IgnoreSideEffects: | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 1147 | return checkingPotentialConstantExpression() || | 
|  | 1148 | checkingForUndefinedBehavior(); | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1149 | } | 
| Aaron Ballman | f682f53 | 2013-11-06 18:15:02 +0000 | [diff] [blame] | 1150 | llvm_unreachable("Missed EvalMode case"); | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 1151 | } | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1152 |  | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1153 | /// Notes that we failed to evaluate an expression that other expressions | 
|  | 1154 | /// directly depend on, and determine if we should keep evaluating. This | 
|  | 1155 | /// should only be called if we actually intend to keep evaluating. | 
|  | 1156 | /// | 
|  | 1157 | /// Call noteSideEffect() instead if we may be able to ignore the value that | 
|  | 1158 | /// we failed to evaluate, e.g. if we failed to evaluate Foo() in: | 
|  | 1159 | /// | 
|  | 1160 | /// (Foo(), 1)      // use noteSideEffect | 
|  | 1161 | /// (Foo() || true) // use noteSideEffect | 
|  | 1162 | /// Foo() + 1       // use noteFailure | 
| Justin Bogner | fe183d7 | 2016-10-17 06:46:35 +0000 | [diff] [blame] | 1163 | LLVM_NODISCARD bool noteFailure() { | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1164 | // Failure when evaluating some expression often means there is some | 
|  | 1165 | // subexpression whose evaluation was skipped. Therefore, (because we | 
|  | 1166 | // don't track whether we skipped an expression when unwinding after an | 
|  | 1167 | // evaluation failure) every evaluation failure that bubbles up from a | 
|  | 1168 | // subexpression implies that a side-effect has potentially happened. We | 
|  | 1169 | // skip setting the HasSideEffects flag to true until we decide to | 
|  | 1170 | // continue evaluating after that point, which happens here. | 
|  | 1171 | bool KeepGoing = keepEvaluatingAfterFailure(); | 
|  | 1172 | EvalStatus.HasSideEffects |= KeepGoing; | 
|  | 1173 | return KeepGoing; | 
|  | 1174 | } | 
|  | 1175 |  | 
| Richard Smith | 410306b | 2016-12-12 02:53:20 +0000 | [diff] [blame] | 1176 | class ArrayInitLoopIndex { | 
|  | 1177 | EvalInfo &Info; | 
|  | 1178 | uint64_t OuterIndex; | 
|  | 1179 |  | 
|  | 1180 | public: | 
|  | 1181 | ArrayInitLoopIndex(EvalInfo &Info) | 
|  | 1182 | : Info(Info), OuterIndex(Info.ArrayInitIndex) { | 
|  | 1183 | Info.ArrayInitIndex = 0; | 
|  | 1184 | } | 
|  | 1185 | ~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; } | 
|  | 1186 |  | 
|  | 1187 | operator uint64_t&() { return Info.ArrayInitIndex; } | 
|  | 1188 | }; | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 1189 | }; | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 1190 |  | 
|  | 1191 | /// Object used to treat all foldable expressions as constant expressions. | 
|  | 1192 | struct FoldConstant { | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1193 | EvalInfo &Info; | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 1194 | bool Enabled; | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1195 | bool HadNoPriorDiags; | 
|  | 1196 | EvalInfo::EvaluationMode OldMode; | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 1197 |  | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1198 | explicit FoldConstant(EvalInfo &Info, bool Enabled) | 
|  | 1199 | : Info(Info), | 
|  | 1200 | Enabled(Enabled), | 
|  | 1201 | HadNoPriorDiags(Info.EvalStatus.Diag && | 
|  | 1202 | Info.EvalStatus.Diag->empty() && | 
|  | 1203 | !Info.EvalStatus.HasSideEffects), | 
|  | 1204 | OldMode(Info.EvalMode) { | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 1205 | if (Enabled) | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1206 | Info.EvalMode = EvalInfo::EM_ConstantFold; | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 1207 | } | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1208 | void keepDiagnostics() { Enabled = false; } | 
|  | 1209 | ~FoldConstant() { | 
|  | 1210 | if (Enabled && HadNoPriorDiags && !Info.EvalStatus.Diag->empty() && | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 1211 | !Info.EvalStatus.HasSideEffects) | 
|  | 1212 | Info.EvalStatus.Diag->clear(); | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 1213 | Info.EvalMode = OldMode; | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 1214 | } | 
|  | 1215 | }; | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 1216 |  | 
| James Y Knight | 892b09b | 2018-10-10 02:53:43 +0000 | [diff] [blame] | 1217 | /// RAII object used to set the current evaluation mode to ignore | 
|  | 1218 | /// side-effects. | 
|  | 1219 | struct IgnoreSideEffectsRAII { | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1220 | EvalInfo &Info; | 
|  | 1221 | EvalInfo::EvaluationMode OldMode; | 
| James Y Knight | 892b09b | 2018-10-10 02:53:43 +0000 | [diff] [blame] | 1222 | explicit IgnoreSideEffectsRAII(EvalInfo &Info) | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1223 | : Info(Info), OldMode(Info.EvalMode) { | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 1224 | Info.EvalMode = EvalInfo::EM_IgnoreSideEffects; | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1225 | } | 
|  | 1226 |  | 
| James Y Knight | 892b09b | 2018-10-10 02:53:43 +0000 | [diff] [blame] | 1227 | ~IgnoreSideEffectsRAII() { Info.EvalMode = OldMode; } | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1228 | }; | 
|  | 1229 |  | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1230 | /// RAII object used to optionally suppress diagnostics and side-effects from | 
|  | 1231 | /// a speculative evaluation. | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 1232 | class SpeculativeEvaluationRAII { | 
| Chandler Carruth | bacb80d | 2017-08-16 07:22:49 +0000 | [diff] [blame] | 1233 | EvalInfo *Info = nullptr; | 
| Reid Kleckner | fdb3df6 | 2017-08-15 01:17:47 +0000 | [diff] [blame] | 1234 | Expr::EvalStatus OldStatus; | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 1235 | unsigned OldSpeculativeEvaluationDepth; | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 1236 |  | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1237 | void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) { | 
| Reid Kleckner | fdb3df6 | 2017-08-15 01:17:47 +0000 | [diff] [blame] | 1238 | Info = Other.Info; | 
|  | 1239 | OldStatus = Other.OldStatus; | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 1240 | OldSpeculativeEvaluationDepth = Other.OldSpeculativeEvaluationDepth; | 
| Reid Kleckner | fdb3df6 | 2017-08-15 01:17:47 +0000 | [diff] [blame] | 1241 | Other.Info = nullptr; | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1242 | } | 
|  | 1243 |  | 
|  | 1244 | void maybeRestoreState() { | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1245 | if (!Info) | 
|  | 1246 | return; | 
|  | 1247 |  | 
| Reid Kleckner | fdb3df6 | 2017-08-15 01:17:47 +0000 | [diff] [blame] | 1248 | Info->EvalStatus = OldStatus; | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 1249 | Info->SpeculativeEvaluationDepth = OldSpeculativeEvaluationDepth; | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1250 | } | 
|  | 1251 |  | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 1252 | public: | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1253 | SpeculativeEvaluationRAII() = default; | 
|  | 1254 |  | 
|  | 1255 | SpeculativeEvaluationRAII( | 
|  | 1256 | EvalInfo &Info, SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr) | 
| Reid Kleckner | fdb3df6 | 2017-08-15 01:17:47 +0000 | [diff] [blame] | 1257 | : Info(&Info), OldStatus(Info.EvalStatus), | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 1258 | OldSpeculativeEvaluationDepth(Info.SpeculativeEvaluationDepth) { | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 1259 | Info.EvalStatus.Diag = NewDiag; | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 1260 | Info.SpeculativeEvaluationDepth = Info.CallStackDepth + 1; | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 1261 | } | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1262 |  | 
|  | 1263 | SpeculativeEvaluationRAII(const SpeculativeEvaluationRAII &Other) = delete; | 
|  | 1264 | SpeculativeEvaluationRAII(SpeculativeEvaluationRAII &&Other) { | 
|  | 1265 | moveFromAndCancel(std::move(Other)); | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 1266 | } | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 1267 |  | 
|  | 1268 | SpeculativeEvaluationRAII &operator=(SpeculativeEvaluationRAII &&Other) { | 
|  | 1269 | maybeRestoreState(); | 
|  | 1270 | moveFromAndCancel(std::move(Other)); | 
|  | 1271 | return *this; | 
|  | 1272 | } | 
|  | 1273 |  | 
|  | 1274 | ~SpeculativeEvaluationRAII() { maybeRestoreState(); } | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 1275 | }; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 1276 |  | 
|  | 1277 | /// RAII object wrapping a full-expression or block scope, and handling | 
|  | 1278 | /// the ending of the lifetime of temporaries created within it. | 
|  | 1279 | template<bool IsFullExpression> | 
|  | 1280 | class ScopeRAII { | 
|  | 1281 | EvalInfo &Info; | 
|  | 1282 | unsigned OldStackSize; | 
|  | 1283 | public: | 
|  | 1284 | ScopeRAII(EvalInfo &Info) | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 1285 | : Info(Info), OldStackSize(Info.CleanupStack.size()) { | 
|  | 1286 | // Push a new temporary version. This is needed to distinguish between | 
|  | 1287 | // temporaries created in different iterations of a loop. | 
|  | 1288 | Info.CurrentCall->pushTempVersion(); | 
|  | 1289 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1290 | bool destroy(bool RunDestructors = true) { | 
|  | 1291 | bool OK = cleanup(Info, RunDestructors, OldStackSize); | 
|  | 1292 | OldStackSize = -1U; | 
|  | 1293 | return OK; | 
|  | 1294 | } | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 1295 | ~ScopeRAII() { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1296 | if (OldStackSize != -1U) | 
|  | 1297 | destroy(false); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 1298 | // Body moved to a static method to encourage the compiler to inline away | 
|  | 1299 | // instances of this class. | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 1300 | Info.CurrentCall->popTempVersion(); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 1301 | } | 
|  | 1302 | private: | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 1303 | static bool cleanup(EvalInfo &Info, bool RunDestructors, | 
|  | 1304 | unsigned OldStackSize) { | 
|  | 1305 | assert(OldStackSize <= Info.CleanupStack.size() && | 
|  | 1306 | "running cleanups out of order?"); | 
|  | 1307 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1308 | // Run all cleanups for a block scope, and non-lifetime-extended cleanups | 
|  | 1309 | // for a full-expression scope. | 
| Richard Smith | 4949473 | 2019-09-27 05:36:16 +0000 | [diff] [blame] | 1310 | bool Success = true; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1311 | for (unsigned I = Info.CleanupStack.size(); I > OldStackSize; --I) { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 1312 | if (!(IsFullExpression && | 
|  | 1313 | Info.CleanupStack[I - 1].isLifetimeExtended())) { | 
| Richard Smith | 4949473 | 2019-09-27 05:36:16 +0000 | [diff] [blame] | 1314 | if (!Info.CleanupStack[I - 1].endLifetime(Info, RunDestructors)) { | 
|  | 1315 | Success = false; | 
|  | 1316 | break; | 
|  | 1317 | } | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 1318 | } | 
|  | 1319 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1320 |  | 
|  | 1321 | // Compact lifetime-extended cleanups. | 
|  | 1322 | auto NewEnd = Info.CleanupStack.begin() + OldStackSize; | 
|  | 1323 | if (IsFullExpression) | 
|  | 1324 | NewEnd = | 
|  | 1325 | std::remove_if(NewEnd, Info.CleanupStack.end(), | 
|  | 1326 | [](Cleanup &C) { return !C.isLifetimeExtended(); }); | 
|  | 1327 | Info.CleanupStack.erase(NewEnd, Info.CleanupStack.end()); | 
| Richard Smith | 4949473 | 2019-09-27 05:36:16 +0000 | [diff] [blame] | 1328 | return Success; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 1329 | } | 
|  | 1330 | }; | 
|  | 1331 | typedef ScopeRAII<false> BlockScopeRAII; | 
|  | 1332 | typedef ScopeRAII<true> FullExpressionRAII; | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 1333 | } | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 1334 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1335 | bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, | 
|  | 1336 | CheckSubobjectKind CSK) { | 
|  | 1337 | if (Invalid) | 
|  | 1338 | return false; | 
|  | 1339 | if (isOnePastTheEnd()) { | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 1340 | Info.CCEDiag(E, diag::note_constexpr_past_end_subobject) | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1341 | << CSK; | 
|  | 1342 | setInvalid(); | 
|  | 1343 | return false; | 
|  | 1344 | } | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 1345 | // Note, we do not diagnose if isMostDerivedAnUnsizedArray(), because there | 
|  | 1346 | // must actually be at least one array element; even a VLA cannot have a | 
|  | 1347 | // bound of zero. And if our index is nonzero, we already had a CCEDiag. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1348 | return true; | 
|  | 1349 | } | 
|  | 1350 |  | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 1351 | void SubobjectDesignator::diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, | 
|  | 1352 | const Expr *E) { | 
|  | 1353 | Info.CCEDiag(E, diag::note_constexpr_unsized_array_indexed); | 
|  | 1354 | // Do not set the designator as invalid: we can represent this situation, | 
|  | 1355 | // and correct handling of __builtin_object_size requires us to do so. | 
|  | 1356 | } | 
|  | 1357 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1358 | void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, | 
| Benjamin Kramer | f6021ec | 2017-03-21 21:35:04 +0000 | [diff] [blame] | 1359 | const Expr *E, | 
|  | 1360 | const APSInt &N) { | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 1361 | // If we're complaining, we must be able to statically determine the size of | 
|  | 1362 | // the most derived array. | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 1363 | if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 1364 | Info.CCEDiag(E, diag::note_constexpr_array_index) | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 1365 | << N << /*array*/ 0 | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 1366 | << static_cast<unsigned>(getMostDerivedArraySize()); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1367 | else | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 1368 | Info.CCEDiag(E, diag::note_constexpr_array_index) | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 1369 | << N << /*non-array*/ 1; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1370 | setInvalid(); | 
|  | 1371 | } | 
|  | 1372 |  | 
| Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 1373 | CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, | 
|  | 1374 | const FunctionDecl *Callee, const LValue *This, | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 1375 | APValue *Arguments) | 
| Samuel Antao | 1197a16 | 2016-09-19 18:13:13 +0000 | [diff] [blame] | 1376 | : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This), | 
|  | 1377 | Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) { | 
| Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 1378 | Info.CurrentCall = this; | 
|  | 1379 | ++Info.CallStackDepth; | 
|  | 1380 | } | 
|  | 1381 |  | 
|  | 1382 | CallStackFrame::~CallStackFrame() { | 
|  | 1383 | assert(Info.CurrentCall == this && "calls retired out of order"); | 
|  | 1384 | --Info.CallStackDepth; | 
|  | 1385 | Info.CurrentCall = Caller; | 
|  | 1386 | } | 
|  | 1387 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 1388 | static bool isRead(AccessKinds AK) { | 
|  | 1389 | return AK == AK_Read || AK == AK_ReadObjectRepresentation; | 
|  | 1390 | } | 
|  | 1391 |  | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 1392 | static bool isModification(AccessKinds AK) { | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 1393 | switch (AK) { | 
|  | 1394 | case AK_Read: | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 1395 | case AK_ReadObjectRepresentation: | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 1396 | case AK_MemberCall: | 
|  | 1397 | case AK_DynamicCast: | 
| Richard Smith | a933030 | 2019-05-17 19:19:28 +0000 | [diff] [blame] | 1398 | case AK_TypeId: | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 1399 | return false; | 
|  | 1400 | case AK_Assign: | 
|  | 1401 | case AK_Increment: | 
|  | 1402 | case AK_Decrement: | 
| Richard Smith | b542602 | 2019-10-03 00:39:35 +0000 | [diff] [blame] | 1403 | case AK_Construct: | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 1404 | case AK_Destroy: | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 1405 | return true; | 
|  | 1406 | } | 
|  | 1407 | llvm_unreachable("unknown access kind"); | 
|  | 1408 | } | 
|  | 1409 |  | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 1410 | static bool isAnyAccess(AccessKinds AK) { | 
|  | 1411 | return isRead(AK) || isModification(AK); | 
|  | 1412 | } | 
|  | 1413 |  | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 1414 | /// Is this an access per the C++ definition? | 
|  | 1415 | static bool isFormalAccess(AccessKinds AK) { | 
| Richard Smith | b542602 | 2019-10-03 00:39:35 +0000 | [diff] [blame] | 1416 | return isAnyAccess(AK) && AK != AK_Construct && AK != AK_Destroy; | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 1417 | } | 
|  | 1418 |  | 
| Richard Smith | f6f003a | 2011-12-16 19:06:07 +0000 | [diff] [blame] | 1419 | namespace { | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 1420 | struct ComplexValue { | 
|  | 1421 | private: | 
|  | 1422 | bool IsInt; | 
|  | 1423 |  | 
|  | 1424 | public: | 
|  | 1425 | APSInt IntReal, IntImag; | 
|  | 1426 | APFloat FloatReal, FloatImag; | 
|  | 1427 |  | 
| Stephan Bergmann | 17c7f70 | 2016-12-14 11:57:17 +0000 | [diff] [blame] | 1428 | ComplexValue() : FloatReal(APFloat::Bogus()), FloatImag(APFloat::Bogus()) {} | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 1429 |  | 
|  | 1430 | void makeComplexFloat() { IsInt = false; } | 
|  | 1431 | bool isComplexFloat() const { return !IsInt; } | 
|  | 1432 | APFloat &getComplexFloatReal() { return FloatReal; } | 
|  | 1433 | APFloat &getComplexFloatImag() { return FloatImag; } | 
|  | 1434 |  | 
|  | 1435 | void makeComplexInt() { IsInt = true; } | 
|  | 1436 | bool isComplexInt() const { return IsInt; } | 
|  | 1437 | APSInt &getComplexIntReal() { return IntReal; } | 
|  | 1438 | APSInt &getComplexIntImag() { return IntImag; } | 
|  | 1439 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1440 | void moveInto(APValue &v) const { | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 1441 | if (isComplexFloat()) | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1442 | v = APValue(FloatReal, FloatImag); | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 1443 | else | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1444 | v = APValue(IntReal, IntImag); | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 1445 | } | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1446 | void setFrom(const APValue &v) { | 
| John McCall | c07a0c7 | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 1447 | assert(v.isComplexFloat() || v.isComplexInt()); | 
|  | 1448 | if (v.isComplexFloat()) { | 
|  | 1449 | makeComplexFloat(); | 
|  | 1450 | FloatReal = v.getComplexFloatReal(); | 
|  | 1451 | FloatImag = v.getComplexFloatImag(); | 
|  | 1452 | } else { | 
|  | 1453 | makeComplexInt(); | 
|  | 1454 | IntReal = v.getComplexIntReal(); | 
|  | 1455 | IntImag = v.getComplexIntImag(); | 
|  | 1456 | } | 
|  | 1457 | } | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 1458 | }; | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 1459 |  | 
|  | 1460 | struct LValue { | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 1461 | APValue::LValueBase Base; | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 1462 | CharUnits Offset; | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 1463 | SubobjectDesignator Designator; | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 1464 | bool IsNullPtr : 1; | 
|  | 1465 | bool InvalidBase : 1; | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 1466 |  | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 1467 | const APValue::LValueBase getLValueBase() const { return Base; } | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 1468 | CharUnits &getLValueOffset() { return Offset; } | 
| Richard Smith | 8b3497e | 2011-10-31 01:37:14 +0000 | [diff] [blame] | 1469 | const CharUnits &getLValueOffset() const { return Offset; } | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 1470 | SubobjectDesignator &getLValueDesignator() { return Designator; } | 
|  | 1471 | const SubobjectDesignator &getLValueDesignator() const { return Designator;} | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 1472 | bool isNullPointer() const { return IsNullPtr;} | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 1473 |  | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 1474 | unsigned getLValueCallIndex() const { return Base.getCallIndex(); } | 
|  | 1475 | unsigned getLValueVersion() const { return Base.getVersion(); } | 
|  | 1476 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1477 | void moveInto(APValue &V) const { | 
|  | 1478 | if (Designator.Invalid) | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 1479 | V = APValue(Base, Offset, APValue::NoLValuePath(), IsNullPtr); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 1480 | else { | 
|  | 1481 | assert(!InvalidBase && "APValues can't handle invalid LValue bases"); | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1482 | V = APValue(Base, Offset, Designator.Entries, | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 1483 | Designator.IsOnePastTheEnd, IsNullPtr); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 1484 | } | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 1485 | } | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1486 | void setFrom(ASTContext &Ctx, const APValue &V) { | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 1487 | assert(V.isLValue() && "Setting LValue from a non-LValue?"); | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 1488 | Base = V.getLValueBase(); | 
|  | 1489 | Offset = V.getLValueOffset(); | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1490 | InvalidBase = false; | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1491 | Designator = SubobjectDesignator(Ctx, V); | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 1492 | IsNullPtr = V.isNullPointer(); | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 1493 | } | 
|  | 1494 |  | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 1495 | void set(APValue::LValueBase B, bool BInvalid = false) { | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 1496 | #ifndef NDEBUG | 
|  | 1497 | // We only allow a few types of invalid bases. Enforce that here. | 
|  | 1498 | if (BInvalid) { | 
|  | 1499 | const auto *E = B.get<const Expr *>(); | 
|  | 1500 | assert((isa<MemberExpr>(E) || tryUnwrapAllocSizeCall(E)) && | 
|  | 1501 | "Unexpected type of invalid base"); | 
|  | 1502 | } | 
|  | 1503 | #endif | 
|  | 1504 |  | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 1505 | Base = B; | 
| Tim Northover | 0150333 | 2017-05-26 02:16:00 +0000 | [diff] [blame] | 1506 | Offset = CharUnits::fromQuantity(0); | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1507 | InvalidBase = BInvalid; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1508 | Designator = SubobjectDesignator(getType(B)); | 
| Tim Northover | 0150333 | 2017-05-26 02:16:00 +0000 | [diff] [blame] | 1509 | IsNullPtr = false; | 
|  | 1510 | } | 
|  | 1511 |  | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 1512 | void setNull(ASTContext &Ctx, QualType PointerTy) { | 
| Tim Northover | 0150333 | 2017-05-26 02:16:00 +0000 | [diff] [blame] | 1513 | Base = (Expr *)nullptr; | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 1514 | Offset = | 
|  | 1515 | CharUnits::fromQuantity(Ctx.getTargetNullPointerValue(PointerTy)); | 
| Tim Northover | 0150333 | 2017-05-26 02:16:00 +0000 | [diff] [blame] | 1516 | InvalidBase = false; | 
| Tim Northover | 0150333 | 2017-05-26 02:16:00 +0000 | [diff] [blame] | 1517 | Designator = SubobjectDesignator(PointerTy->getPointeeType()); | 
|  | 1518 | IsNullPtr = true; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1519 | } | 
|  | 1520 |  | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1521 | void setInvalid(APValue::LValueBase B, unsigned I = 0) { | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 1522 | set(B, true); | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 1523 | } | 
|  | 1524 |  | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 1525 | std::string toString(ASTContext &Ctx, QualType T) const { | 
|  | 1526 | APValue Printable; | 
|  | 1527 | moveInto(Printable); | 
|  | 1528 | return Printable.getAsString(Ctx, T); | 
|  | 1529 | } | 
|  | 1530 |  | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 1531 | private: | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1532 | // Check that this LValue is not based on a null pointer. If it is, produce | 
|  | 1533 | // a diagnostic and mark the designator as invalid. | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 1534 | template <typename GenDiagType> | 
|  | 1535 | bool checkNullPointerDiagnosingWith(const GenDiagType &GenDiag) { | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1536 | if (Designator.Invalid) | 
|  | 1537 | return false; | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 1538 | if (IsNullPtr) { | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 1539 | GenDiag(); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1540 | Designator.setInvalid(); | 
|  | 1541 | return false; | 
|  | 1542 | } | 
|  | 1543 | return true; | 
|  | 1544 | } | 
|  | 1545 |  | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 1546 | public: | 
|  | 1547 | bool checkNullPointer(EvalInfo &Info, const Expr *E, | 
|  | 1548 | CheckSubobjectKind CSK) { | 
|  | 1549 | return checkNullPointerDiagnosingWith([&Info, E, CSK] { | 
|  | 1550 | Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; | 
|  | 1551 | }); | 
|  | 1552 | } | 
|  | 1553 |  | 
|  | 1554 | bool checkNullPointerForFoldAccess(EvalInfo &Info, const Expr *E, | 
|  | 1555 | AccessKinds AK) { | 
|  | 1556 | return checkNullPointerDiagnosingWith([&Info, E, AK] { | 
|  | 1557 | Info.FFDiag(E, diag::note_constexpr_access_null) << AK; | 
|  | 1558 | }); | 
|  | 1559 | } | 
|  | 1560 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1561 | // Check this LValue refers to an object. If not, set the designator to be | 
|  | 1562 | // invalid and emit a diagnostic. | 
|  | 1563 | bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { | 
| Richard Smith | 6c6bbfa | 2014-04-08 12:19:28 +0000 | [diff] [blame] | 1564 | return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) && | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1565 | Designator.checkSubobject(Info, E, CSK); | 
|  | 1566 | } | 
|  | 1567 |  | 
|  | 1568 | void addDecl(EvalInfo &Info, const Expr *E, | 
|  | 1569 | const Decl *D, bool Virtual = false) { | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 1570 | if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base)) | 
|  | 1571 | Designator.addDeclUnchecked(D, Virtual); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1572 | } | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 1573 | void addUnsizedArray(EvalInfo &Info, const Expr *E, QualType ElemTy) { | 
|  | 1574 | if (!Designator.Entries.empty()) { | 
|  | 1575 | Info.CCEDiag(E, diag::note_constexpr_unsupported_unsized_array); | 
|  | 1576 | Designator.setInvalid(); | 
|  | 1577 | return; | 
|  | 1578 | } | 
| Richard Smith | efdb503 | 2017-11-15 03:03:56 +0000 | [diff] [blame] | 1579 | if (checkSubobject(Info, E, CSK_ArrayToPointer)) { | 
|  | 1580 | assert(getType(Base)->isPointerType() || getType(Base)->isArrayType()); | 
|  | 1581 | Designator.FirstEntryIsAnUnsizedArray = true; | 
|  | 1582 | Designator.addUnsizedArrayUnchecked(ElemTy); | 
|  | 1583 | } | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 1584 | } | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1585 | void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) { | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 1586 | if (checkSubobject(Info, E, CSK_ArrayToPointer)) | 
|  | 1587 | Designator.addArrayUnchecked(CAT); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 1588 | } | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 1589 | void addComplex(EvalInfo &Info, const Expr *E, QualType EltTy, bool Imag) { | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 1590 | if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) | 
|  | 1591 | Designator.addComplexUnchecked(EltTy, Imag); | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 1592 | } | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 1593 | void clearIsNullPointer() { | 
|  | 1594 | IsNullPtr = false; | 
|  | 1595 | } | 
| Benjamin Kramer | f6021ec | 2017-03-21 21:35:04 +0000 | [diff] [blame] | 1596 | void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, | 
|  | 1597 | const APSInt &Index, CharUnits ElementSize) { | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 1598 | // An index of 0 has no effect. (In C, adding 0 to a null pointer is UB, | 
|  | 1599 | // but we're not required to diagnose it and it's valid in C++.) | 
|  | 1600 | if (!Index) | 
|  | 1601 | return; | 
|  | 1602 |  | 
|  | 1603 | // Compute the new offset in the appropriate width, wrapping at 64 bits. | 
|  | 1604 | // FIXME: When compiling for a 32-bit target, we should use 32-bit | 
|  | 1605 | // offsets. | 
|  | 1606 | uint64_t Offset64 = Offset.getQuantity(); | 
|  | 1607 | uint64_t ElemSize64 = ElementSize.getQuantity(); | 
|  | 1608 | uint64_t Index64 = Index.extOrTrunc(64).getZExtValue(); | 
|  | 1609 | Offset = CharUnits::fromQuantity(Offset64 + ElemSize64 * Index64); | 
|  | 1610 |  | 
|  | 1611 | if (checkNullPointer(Info, E, CSK_ArrayIndex)) | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 1612 | Designator.adjustIndex(Info, E, Index); | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 1613 | clearIsNullPointer(); | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 1614 | } | 
|  | 1615 | void adjustOffset(CharUnits N) { | 
|  | 1616 | Offset += N; | 
|  | 1617 | if (N.getQuantity()) | 
|  | 1618 | clearIsNullPointer(); | 
| John McCall | c07a0c7 | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 1619 | } | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 1620 | }; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 1621 |  | 
|  | 1622 | struct MemberPtr { | 
|  | 1623 | MemberPtr() {} | 
|  | 1624 | explicit MemberPtr(const ValueDecl *Decl) : | 
|  | 1625 | DeclAndIsDerivedMember(Decl, false), Path() {} | 
|  | 1626 |  | 
|  | 1627 | /// The member or (direct or indirect) field referred to by this member | 
|  | 1628 | /// pointer, or 0 if this is a null member pointer. | 
|  | 1629 | const ValueDecl *getDecl() const { | 
|  | 1630 | return DeclAndIsDerivedMember.getPointer(); | 
|  | 1631 | } | 
|  | 1632 | /// Is this actually a member of some type derived from the relevant class? | 
|  | 1633 | bool isDerivedMember() const { | 
|  | 1634 | return DeclAndIsDerivedMember.getInt(); | 
|  | 1635 | } | 
|  | 1636 | /// Get the class which the declaration actually lives in. | 
|  | 1637 | const CXXRecordDecl *getContainingRecord() const { | 
|  | 1638 | return cast<CXXRecordDecl>( | 
|  | 1639 | DeclAndIsDerivedMember.getPointer()->getDeclContext()); | 
|  | 1640 | } | 
|  | 1641 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1642 | void moveInto(APValue &V) const { | 
|  | 1643 | V = APValue(getDecl(), isDerivedMember(), Path); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 1644 | } | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1645 | void setFrom(const APValue &V) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 1646 | assert(V.isMemberPointer()); | 
|  | 1647 | DeclAndIsDerivedMember.setPointer(V.getMemberPointerDecl()); | 
|  | 1648 | DeclAndIsDerivedMember.setInt(V.isMemberPointerToDerivedMember()); | 
|  | 1649 | Path.clear(); | 
|  | 1650 | ArrayRef<const CXXRecordDecl*> P = V.getMemberPointerPath(); | 
|  | 1651 | Path.insert(Path.end(), P.begin(), P.end()); | 
|  | 1652 | } | 
|  | 1653 |  | 
|  | 1654 | /// DeclAndIsDerivedMember - The member declaration, and a flag indicating | 
|  | 1655 | /// whether the member is a member of some class derived from the class type | 
|  | 1656 | /// of the member pointer. | 
|  | 1657 | llvm::PointerIntPair<const ValueDecl*, 1, bool> DeclAndIsDerivedMember; | 
|  | 1658 | /// Path - The path of base/derived classes from the member declaration's | 
|  | 1659 | /// class (exclusive) to the class type of the member pointer (inclusive). | 
|  | 1660 | SmallVector<const CXXRecordDecl*, 4> Path; | 
|  | 1661 |  | 
|  | 1662 | /// Perform a cast towards the class of the Decl (either up or down the | 
|  | 1663 | /// hierarchy). | 
|  | 1664 | bool castBack(const CXXRecordDecl *Class) { | 
|  | 1665 | assert(!Path.empty()); | 
|  | 1666 | const CXXRecordDecl *Expected; | 
|  | 1667 | if (Path.size() >= 2) | 
|  | 1668 | Expected = Path[Path.size() - 2]; | 
|  | 1669 | else | 
|  | 1670 | Expected = getContainingRecord(); | 
|  | 1671 | if (Expected->getCanonicalDecl() != Class->getCanonicalDecl()) { | 
|  | 1672 | // C++11 [expr.static.cast]p12: In a conversion from (D::*) to (B::*), | 
|  | 1673 | // if B does not contain the original member and is not a base or | 
|  | 1674 | // derived class of the class containing the original member, the result | 
|  | 1675 | // of the cast is undefined. | 
|  | 1676 | // C++11 [conv.mem]p2 does not cover this case for a cast from (B::*) to | 
|  | 1677 | // (D::*). We consider that to be a language defect. | 
|  | 1678 | return false; | 
|  | 1679 | } | 
|  | 1680 | Path.pop_back(); | 
|  | 1681 | return true; | 
|  | 1682 | } | 
|  | 1683 | /// Perform a base-to-derived member pointer cast. | 
|  | 1684 | bool castToDerived(const CXXRecordDecl *Derived) { | 
|  | 1685 | if (!getDecl()) | 
|  | 1686 | return true; | 
|  | 1687 | if (!isDerivedMember()) { | 
|  | 1688 | Path.push_back(Derived); | 
|  | 1689 | return true; | 
|  | 1690 | } | 
|  | 1691 | if (!castBack(Derived)) | 
|  | 1692 | return false; | 
|  | 1693 | if (Path.empty()) | 
|  | 1694 | DeclAndIsDerivedMember.setInt(false); | 
|  | 1695 | return true; | 
|  | 1696 | } | 
|  | 1697 | /// Perform a derived-to-base member pointer cast. | 
|  | 1698 | bool castToBase(const CXXRecordDecl *Base) { | 
|  | 1699 | if (!getDecl()) | 
|  | 1700 | return true; | 
|  | 1701 | if (Path.empty()) | 
|  | 1702 | DeclAndIsDerivedMember.setInt(true); | 
|  | 1703 | if (isDerivedMember()) { | 
|  | 1704 | Path.push_back(Base); | 
|  | 1705 | return true; | 
|  | 1706 | } | 
|  | 1707 | return castBack(Base); | 
|  | 1708 | } | 
|  | 1709 | }; | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 1710 |  | 
| Richard Smith | 7bb0067 | 2012-02-01 01:42:44 +0000 | [diff] [blame] | 1711 | /// Compare two member pointers, which are assumed to be of the same type. | 
|  | 1712 | static bool operator==(const MemberPtr &LHS, const MemberPtr &RHS) { | 
|  | 1713 | if (!LHS.getDecl() || !RHS.getDecl()) | 
|  | 1714 | return !LHS.getDecl() && !RHS.getDecl(); | 
|  | 1715 | if (LHS.getDecl()->getCanonicalDecl() != RHS.getDecl()->getCanonicalDecl()) | 
|  | 1716 | return false; | 
|  | 1717 | return LHS.Path == RHS.Path; | 
|  | 1718 | } | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 1719 | } | 
| Chris Lattner | cdf34e7 | 2008-07-11 22:52:41 +0000 | [diff] [blame] | 1720 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1721 | static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 1722 | static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, | 
|  | 1723 | const LValue &This, const Expr *E, | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 1724 | bool AllowNonLiteralTypes = false); | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 1725 | static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, | 
|  | 1726 | bool InvalidBaseOK = false); | 
|  | 1727 | static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info, | 
|  | 1728 | bool InvalidBaseOK = false); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 1729 | static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, | 
|  | 1730 | EvalInfo &Info); | 
|  | 1731 | static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info); | 
| George Burgess IV | 533ff00 | 2015-12-11 00:23:35 +0000 | [diff] [blame] | 1732 | static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1733 | static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, | 
| Chris Lattner | 6c4d255 | 2009-10-28 23:59:40 +0000 | [diff] [blame] | 1734 | EvalInfo &Info); | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 1735 | static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 1736 | static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 1737 | static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result, | 
|  | 1738 | EvalInfo &Info); | 
| George Burgess IV | 3e3bb95b | 2015-12-02 21:58:08 +0000 | [diff] [blame] | 1739 | static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result); | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 1740 |  | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 1741 | /// Evaluate an integer or fixed point expression into an APResult. | 
|  | 1742 | static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result, | 
|  | 1743 | EvalInfo &Info); | 
|  | 1744 |  | 
|  | 1745 | /// Evaluate only a fixed point expression into an APResult. | 
|  | 1746 | static bool EvaluateFixedPoint(const Expr *E, APFixedPoint &Result, | 
|  | 1747 | EvalInfo &Info); | 
|  | 1748 |  | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 1749 | //===----------------------------------------------------------------------===// | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 1750 | // Misc utilities | 
|  | 1751 | //===----------------------------------------------------------------------===// | 
|  | 1752 |  | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 1753 | /// Negate an APSInt in place, converting it to a signed form if necessary, and | 
|  | 1754 | /// preserving its value (by extending by up to one bit as needed). | 
|  | 1755 | static void negateAsSigned(APSInt &Int) { | 
|  | 1756 | if (Int.isUnsigned() || Int.isMinSignedValue()) { | 
|  | 1757 | Int = Int.extend(Int.getBitWidth() + 1); | 
|  | 1758 | Int.setIsSigned(true); | 
|  | 1759 | } | 
|  | 1760 | Int = -Int; | 
|  | 1761 | } | 
|  | 1762 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1763 | template<typename KeyT> | 
|  | 1764 | APValue &CallStackFrame::createTemporary(const KeyT *Key, QualType T, | 
|  | 1765 | bool IsLifetimeExtended, LValue &LV) { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 1766 | unsigned Version = getTempVersion(); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1767 | APValue::LValueBase Base(Key, Index, Version); | 
|  | 1768 | LV.set(Base); | 
|  | 1769 | APValue &Result = Temporaries[MapKeyTy(Key, Version)]; | 
|  | 1770 | assert(Result.isAbsent() && "temporary created multiple times"); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 1771 |  | 
|  | 1772 | // If we're creating a temporary immediately in the operand of a speculative | 
|  | 1773 | // evaluation, don't register a cleanup to be run outside the speculative | 
|  | 1774 | // evaluation context, since we won't actually be able to initialize this | 
|  | 1775 | // object. | 
|  | 1776 | if (Index <= Info.SpeculativeEvaluationDepth) { | 
|  | 1777 | if (T.isDestructedType()) | 
|  | 1778 | Info.noteSideEffect(); | 
|  | 1779 | } else { | 
|  | 1780 | Info.CleanupStack.push_back(Cleanup(&Result, Base, T, IsLifetimeExtended)); | 
|  | 1781 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 1782 | return Result; | 
|  | 1783 | } | 
|  | 1784 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 1785 | APValue *EvalInfo::createHeapAlloc(const Expr *E, QualType T, LValue &LV) { | 
|  | 1786 | if (NumHeapAllocs > DynamicAllocLValue::getMaxIndex()) { | 
|  | 1787 | FFDiag(E, diag::note_constexpr_heap_alloc_limit_exceeded); | 
|  | 1788 | return nullptr; | 
|  | 1789 | } | 
|  | 1790 |  | 
|  | 1791 | DynamicAllocLValue DA(NumHeapAllocs++); | 
|  | 1792 | LV.set(APValue::LValueBase::getDynamicAlloc(DA, T)); | 
|  | 1793 | auto Result = HeapAllocs.emplace(std::piecewise_construct, | 
|  | 1794 | std::forward_as_tuple(DA), std::tuple<>()); | 
|  | 1795 | assert(Result.second && "reused a heap alloc index?"); | 
|  | 1796 | Result.first->second.AllocExpr = E; | 
|  | 1797 | return &Result.first->second.Value; | 
|  | 1798 | } | 
|  | 1799 |  | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1800 | /// Produce a string describing the given constexpr call. | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1801 | void CallStackFrame::describe(raw_ostream &Out) { | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1802 | unsigned ArgIndex = 0; | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1803 | bool IsMemberCall = isa<CXXMethodDecl>(Callee) && | 
|  | 1804 | !isa<CXXConstructorDecl>(Callee) && | 
|  | 1805 | cast<CXXMethodDecl>(Callee)->isInstance(); | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1806 |  | 
|  | 1807 | if (!IsMemberCall) | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1808 | Out << *Callee << '('; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1809 |  | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1810 | if (This && IsMemberCall) { | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1811 | APValue Val; | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1812 | This->moveInto(Val); | 
|  | 1813 | Val.printPretty(Out, Info.Ctx, | 
|  | 1814 | This->Designator.MostDerivedType); | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1815 | // FIXME: Add parens around Val if needed. | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1816 | Out << "->" << *Callee << '('; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1817 | IsMemberCall = false; | 
|  | 1818 | } | 
|  | 1819 |  | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1820 | for (FunctionDecl::param_const_iterator I = Callee->param_begin(), | 
|  | 1821 | E = Callee->param_end(); I != E; ++I, ++ArgIndex) { | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1822 | if (ArgIndex > (unsigned)IsMemberCall) | 
|  | 1823 | Out << ", "; | 
|  | 1824 |  | 
|  | 1825 | const ParmVarDecl *Param = *I; | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1826 | const APValue &Arg = Arguments[ArgIndex]; | 
|  | 1827 | Arg.printPretty(Out, Info.Ctx, Param->getType()); | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1828 |  | 
|  | 1829 | if (ArgIndex == 0 && IsMemberCall) | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 1830 | Out << "->" << *Callee << '('; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 1831 | } | 
|  | 1832 |  | 
|  | 1833 | Out << ')'; | 
|  | 1834 | } | 
|  | 1835 |  | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 1836 | /// Evaluate an expression to see if it had side-effects, and discard its | 
|  | 1837 | /// result. | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 1838 | /// \return \c true if the caller should keep evaluating. | 
|  | 1839 | static bool EvaluateIgnoredValue(EvalInfo &Info, const Expr *E) { | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 1840 | APValue Scratch; | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 1841 | if (!Evaluate(Scratch, Info, E)) | 
|  | 1842 | // We don't need the value, but we might have skipped a side effect here. | 
|  | 1843 | return Info.noteSideEffect(); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 1844 | return true; | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 1845 | } | 
|  | 1846 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 1847 | /// Should this call expression be treated as a string literal? | 
|  | 1848 | static bool IsStringLiteralCall(const CallExpr *E) { | 
| Alp Toker | a724cff | 2013-12-28 21:59:02 +0000 | [diff] [blame] | 1849 | unsigned Builtin = E->getBuiltinCallee(); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 1850 | return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString || | 
|  | 1851 | Builtin == Builtin::BI__builtin___NSStringMakeConstantString); | 
|  | 1852 | } | 
|  | 1853 |  | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 1854 | static bool IsGlobalLValue(APValue::LValueBase B) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 1855 | // C++11 [expr.const]p3 An address constant expression is a prvalue core | 
|  | 1856 | // constant expression of pointer type that evaluates to... | 
|  | 1857 |  | 
|  | 1858 | // ... a null pointer value, or a prvalue core constant expression of type | 
|  | 1859 | // std::nullptr_t. | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 1860 | if (!B) return true; | 
| John McCall | 9500760 | 2010-05-10 23:27:23 +0000 | [diff] [blame] | 1861 |  | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 1862 | if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) { | 
|  | 1863 | // ... the address of an object with static storage duration, | 
|  | 1864 | if (const VarDecl *VD = dyn_cast<VarDecl>(D)) | 
|  | 1865 | return VD->hasGlobalStorage(); | 
|  | 1866 | // ... the address of a function, | 
|  | 1867 | return isa<FunctionDecl>(D); | 
|  | 1868 | } | 
|  | 1869 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 1870 | if (B.is<TypeInfoLValue>() || B.is<DynamicAllocLValue>()) | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 1871 | return true; | 
|  | 1872 |  | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 1873 | const Expr *E = B.get<const Expr*>(); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 1874 | switch (E->getStmtClass()) { | 
|  | 1875 | default: | 
|  | 1876 | return false; | 
| Richard Smith | 0dea49e | 2012-02-18 04:58:18 +0000 | [diff] [blame] | 1877 | case Expr::CompoundLiteralExprClass: { | 
|  | 1878 | const CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E); | 
|  | 1879 | return CLE->isFileScope() && CLE->isLValue(); | 
|  | 1880 | } | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 1881 | case Expr::MaterializeTemporaryExprClass: | 
|  | 1882 | // A materialized temporary might have been lifetime-extended to static | 
|  | 1883 | // storage duration. | 
|  | 1884 | return cast<MaterializeTemporaryExpr>(E)->getStorageDuration() == SD_Static; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 1885 | // A string literal has static storage duration. | 
|  | 1886 | case Expr::StringLiteralClass: | 
|  | 1887 | case Expr::PredefinedExprClass: | 
|  | 1888 | case Expr::ObjCStringLiteralClass: | 
|  | 1889 | case Expr::ObjCEncodeExprClass: | 
| Francois Pichet | 0066db9 | 2012-04-16 04:08:35 +0000 | [diff] [blame] | 1890 | case Expr::CXXUuidofExprClass: | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 1891 | return true; | 
| Akira Hatanaka | 1488ee4 | 2019-03-08 04:45:37 +0000 | [diff] [blame] | 1892 | case Expr::ObjCBoxedExprClass: | 
|  | 1893 | return cast<ObjCBoxedExpr>(E)->isExpressibleAsConstantInitializer(); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 1894 | case Expr::CallExprClass: | 
|  | 1895 | return IsStringLiteralCall(cast<CallExpr>(E)); | 
|  | 1896 | // For GCC compatibility, &&label has static storage duration. | 
|  | 1897 | case Expr::AddrLabelExprClass: | 
|  | 1898 | return true; | 
|  | 1899 | // A Block literal expression may be used as the initialization value for | 
|  | 1900 | // Block variables at global or local static scope. | 
|  | 1901 | case Expr::BlockExprClass: | 
|  | 1902 | return !cast<BlockExpr>(E)->getBlockDecl()->hasCaptures(); | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 1903 | case Expr::ImplicitValueInitExprClass: | 
|  | 1904 | // FIXME: | 
|  | 1905 | // We can never form an lvalue with an implicit value initialization as its | 
|  | 1906 | // base through expression evaluation, so these only appear in one case: the | 
|  | 1907 | // implicit variable declaration we invent when checking whether a constexpr | 
|  | 1908 | // constructor can produce a constant expression. We must assume that such | 
|  | 1909 | // an expression might be a global lvalue. | 
|  | 1910 | return true; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 1911 | } | 
| John McCall | 9500760 | 2010-05-10 23:27:23 +0000 | [diff] [blame] | 1912 | } | 
|  | 1913 |  | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 1914 | static const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { | 
|  | 1915 | return LVal.Base.dyn_cast<const ValueDecl*>(); | 
|  | 1916 | } | 
|  | 1917 |  | 
|  | 1918 | static bool IsLiteralLValue(const LValue &Value) { | 
|  | 1919 | if (Value.getLValueCallIndex()) | 
|  | 1920 | return false; | 
|  | 1921 | const Expr *E = Value.Base.dyn_cast<const Expr*>(); | 
|  | 1922 | return E && !isa<MaterializeTemporaryExpr>(E); | 
|  | 1923 | } | 
|  | 1924 |  | 
|  | 1925 | static bool IsWeakLValue(const LValue &Value) { | 
|  | 1926 | const ValueDecl *Decl = GetLValueBaseDecl(Value); | 
|  | 1927 | return Decl && Decl->isWeak(); | 
|  | 1928 | } | 
|  | 1929 |  | 
|  | 1930 | static bool isZeroSized(const LValue &Value) { | 
|  | 1931 | const ValueDecl *Decl = GetLValueBaseDecl(Value); | 
|  | 1932 | if (Decl && isa<VarDecl>(Decl)) { | 
|  | 1933 | QualType Ty = Decl->getType(); | 
|  | 1934 | if (Ty->isArrayType()) | 
|  | 1935 | return Ty->isIncompleteType() || | 
|  | 1936 | Decl->getASTContext().getTypeSize(Ty) == 0; | 
|  | 1937 | } | 
|  | 1938 | return false; | 
|  | 1939 | } | 
|  | 1940 |  | 
|  | 1941 | static bool HasSameBase(const LValue &A, const LValue &B) { | 
|  | 1942 | if (!A.getLValueBase()) | 
|  | 1943 | return !B.getLValueBase(); | 
|  | 1944 | if (!B.getLValueBase()) | 
|  | 1945 | return false; | 
|  | 1946 |  | 
|  | 1947 | if (A.getLValueBase().getOpaqueValue() != | 
|  | 1948 | B.getLValueBase().getOpaqueValue()) { | 
|  | 1949 | const Decl *ADecl = GetLValueBaseDecl(A); | 
|  | 1950 | if (!ADecl) | 
|  | 1951 | return false; | 
|  | 1952 | const Decl *BDecl = GetLValueBaseDecl(B); | 
|  | 1953 | if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl()) | 
|  | 1954 | return false; | 
|  | 1955 | } | 
|  | 1956 |  | 
|  | 1957 | return IsGlobalLValue(A.getLValueBase()) || | 
|  | 1958 | (A.getLValueCallIndex() == B.getLValueCallIndex() && | 
|  | 1959 | A.getLValueVersion() == B.getLValueVersion()); | 
|  | 1960 | } | 
|  | 1961 |  | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 1962 | static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) { | 
|  | 1963 | assert(Base && "no location for a null lvalue"); | 
|  | 1964 | const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); | 
|  | 1965 | if (VD) | 
|  | 1966 | Info.Note(VD->getLocation(), diag::note_declared_at); | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 1967 | else if (const Expr *E = Base.dyn_cast<const Expr*>()) | 
|  | 1968 | Info.Note(E->getExprLoc(), diag::note_constexpr_temporary_here); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 1969 | else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) { | 
|  | 1970 | // FIXME: Produce a note for dangling pointers too. | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 1971 | if (Optional<DynAlloc*> Alloc = Info.lookupDynamicAlloc(DA)) | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 1972 | Info.Note((*Alloc)->AllocExpr->getExprLoc(), | 
|  | 1973 | diag::note_constexpr_dynamic_alloc_here); | 
|  | 1974 | } | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 1975 | // We have no information to show for a typeid(T) object. | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 1976 | } | 
|  | 1977 |  | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 1978 | enum class CheckEvaluationResultKind { | 
|  | 1979 | ConstantExpression, | 
|  | 1980 | FullyInitialized, | 
|  | 1981 | }; | 
|  | 1982 |  | 
|  | 1983 | /// Materialized temporaries that we've already checked to determine if they're | 
|  | 1984 | /// initializsed by a constant expression. | 
|  | 1985 | using CheckedTemporaries = | 
|  | 1986 | llvm::SmallPtrSet<const MaterializeTemporaryExpr *, 8>; | 
|  | 1987 |  | 
|  | 1988 | static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, | 
|  | 1989 | EvalInfo &Info, SourceLocation DiagLoc, | 
|  | 1990 | QualType Type, const APValue &Value, | 
|  | 1991 | Expr::ConstExprUsage Usage, | 
|  | 1992 | SourceLocation SubobjectLoc, | 
|  | 1993 | CheckedTemporaries &CheckedTemps); | 
|  | 1994 |  | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 1995 | /// Check that this reference or pointer core constant expression is a valid | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 1996 | /// value for an address or reference constant expression. Return true if we | 
|  | 1997 | /// can fold this expression, whether or not it's a constant expression. | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 1998 | static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 1999 | QualType Type, const LValue &LVal, | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2000 | Expr::ConstExprUsage Usage, | 
|  | 2001 | CheckedTemporaries &CheckedTemps) { | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2002 | bool IsReferenceType = Type->isReferenceType(); | 
|  | 2003 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2004 | APValue::LValueBase Base = LVal.getLValueBase(); | 
|  | 2005 | const SubobjectDesignator &Designator = LVal.getLValueDesignator(); | 
|  | 2006 |  | 
| Richard Smith | 0dea49e | 2012-02-18 04:58:18 +0000 | [diff] [blame] | 2007 | // Check that the object is a global. Note that the fake 'this' object we | 
|  | 2008 | // manufacture when checking potential constant expressions is conservatively | 
|  | 2009 | // assumed to be global here. | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2010 | if (!IsGlobalLValue(Base)) { | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 2011 | if (Info.getLangOpts().CPlusPlus11) { | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2012 | const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2013 | Info.FFDiag(Loc, diag::note_constexpr_non_global, 1) | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2014 | << IsReferenceType << !Designator.Entries.empty() | 
|  | 2015 | << !!VD << VD; | 
|  | 2016 | NoteLValueLocation(Info, Base); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2017 | } else { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2018 | Info.FFDiag(Loc); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2019 | } | 
| Richard Smith | 02ab9c2 | 2012-01-12 06:08:57 +0000 | [diff] [blame] | 2020 | // Don't allow references to temporaries to escape. | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 2021 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 2022 | } | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 2023 | assert((Info.checkingPotentialConstantExpression() || | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2024 | LVal.getLValueCallIndex() == 0) && | 
|  | 2025 | "have call index for global lvalue"); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2026 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 2027 | if (Base.is<DynamicAllocLValue>()) { | 
|  | 2028 | Info.FFDiag(Loc, diag::note_constexpr_dynamic_alloc) | 
|  | 2029 | << IsReferenceType << !Designator.Entries.empty(); | 
|  | 2030 | NoteLValueLocation(Info, Base); | 
|  | 2031 | return false; | 
|  | 2032 | } | 
|  | 2033 |  | 
| Hans Wennborg | cb9ad99 | 2012-08-29 18:27:29 +0000 | [diff] [blame] | 2034 | if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { | 
|  | 2035 | if (const VarDecl *Var = dyn_cast<const VarDecl>(VD)) { | 
| David Majnemer | 0c43d80 | 2014-06-25 08:15:07 +0000 | [diff] [blame] | 2036 | // Check if this is a thread-local variable. | 
| Richard Smith | fd3834f | 2013-04-13 02:43:54 +0000 | [diff] [blame] | 2037 | if (Var->getTLSKind()) | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 2038 | // FIXME: Diagnostic! | 
| Hans Wennborg | cb9ad99 | 2012-08-29 18:27:29 +0000 | [diff] [blame] | 2039 | return false; | 
| David Majnemer | 0c43d80 | 2014-06-25 08:15:07 +0000 | [diff] [blame] | 2040 |  | 
| Hans Wennborg | 82dd877 | 2014-06-25 22:19:48 +0000 | [diff] [blame] | 2041 | // A dllimport variable never acts like a constant. | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 2042 | if (Usage == Expr::EvaluateForCodeGen && Var->hasAttr<DLLImportAttr>()) | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 2043 | // FIXME: Diagnostic! | 
| David Majnemer | 0c43d80 | 2014-06-25 08:15:07 +0000 | [diff] [blame] | 2044 | return false; | 
|  | 2045 | } | 
|  | 2046 | if (const auto *FD = dyn_cast<const FunctionDecl>(VD)) { | 
|  | 2047 | // __declspec(dllimport) must be handled very carefully: | 
|  | 2048 | // We must never initialize an expression with the thunk in C++. | 
|  | 2049 | // Doing otherwise would allow the same id-expression to yield | 
|  | 2050 | // different addresses for the same function in different translation | 
|  | 2051 | // units.  However, this means that we must dynamically initialize the | 
|  | 2052 | // expression with the contents of the import address table at runtime. | 
|  | 2053 | // | 
|  | 2054 | // The C language has no notion of ODR; furthermore, it has no notion of | 
|  | 2055 | // dynamic initialization.  This means that we are permitted to | 
|  | 2056 | // perform initialization with the address of the thunk. | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 2057 | if (Info.getLangOpts().CPlusPlus && Usage == Expr::EvaluateForCodeGen && | 
|  | 2058 | FD->hasAttr<DLLImportAttr>()) | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 2059 | // FIXME: Diagnostic! | 
| David Majnemer | 0c43d80 | 2014-06-25 08:15:07 +0000 | [diff] [blame] | 2060 | return false; | 
| Hans Wennborg | cb9ad99 | 2012-08-29 18:27:29 +0000 | [diff] [blame] | 2061 | } | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2062 | } else if (const auto *MTE = dyn_cast_or_null<MaterializeTemporaryExpr>( | 
|  | 2063 | Base.dyn_cast<const Expr *>())) { | 
|  | 2064 | if (CheckedTemps.insert(MTE).second) { | 
| Richard Smith | 1e8c085 | 2019-09-29 06:22:54 +0000 | [diff] [blame] | 2065 | QualType TempType = getType(Base); | 
|  | 2066 | if (TempType.isDestructedType()) { | 
|  | 2067 | Info.FFDiag(MTE->getExprLoc(), | 
|  | 2068 | diag::note_constexpr_unsupported_tempoarary_nontrivial_dtor) | 
|  | 2069 | << TempType; | 
|  | 2070 | return false; | 
|  | 2071 | } | 
|  | 2072 |  | 
| Tyker | b0561b3 | 2019-11-17 11:41:55 +0100 | [diff] [blame] | 2073 | APValue *V = MTE->getOrCreateValue(false); | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2074 | assert(V && "evasluation result refers to uninitialised temporary"); | 
|  | 2075 | if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression, | 
| Richard Smith | 1e8c085 | 2019-09-29 06:22:54 +0000 | [diff] [blame] | 2076 | Info, MTE->getExprLoc(), TempType, *V, | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2077 | Usage, SourceLocation(), CheckedTemps)) | 
|  | 2078 | return false; | 
|  | 2079 | } | 
| Hans Wennborg | cb9ad99 | 2012-08-29 18:27:29 +0000 | [diff] [blame] | 2080 | } | 
|  | 2081 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2082 | // Allow address constant expressions to be past-the-end pointers. This is | 
|  | 2083 | // an extension: the standard requires them to point to an object. | 
|  | 2084 | if (!IsReferenceType) | 
|  | 2085 | return true; | 
|  | 2086 |  | 
|  | 2087 | // A reference constant expression must refer to an object. | 
|  | 2088 | if (!Base) { | 
|  | 2089 | // FIXME: diagnostic | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2090 | Info.CCEDiag(Loc); | 
| Richard Smith | 02ab9c2 | 2012-01-12 06:08:57 +0000 | [diff] [blame] | 2091 | return true; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2092 | } | 
|  | 2093 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2094 | // Does this refer one past the end of some object? | 
| Richard Smith | 33b44ab | 2014-07-23 23:50:25 +0000 | [diff] [blame] | 2095 | if (!Designator.Invalid && Designator.isOnePastTheEnd()) { | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2096 | const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2097 | Info.FFDiag(Loc, diag::note_constexpr_past_end, 1) | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2098 | << !Designator.Entries.empty() << !!VD << VD; | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2099 | NoteLValueLocation(Info, Base); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2100 | } | 
|  | 2101 |  | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 2102 | return true; | 
|  | 2103 | } | 
|  | 2104 |  | 
| Reid Kleckner | cd016d8 | 2017-07-07 22:04:29 +0000 | [diff] [blame] | 2105 | /// Member pointers are constant expressions unless they point to a | 
|  | 2106 | /// non-virtual dllimport member function. | 
|  | 2107 | static bool CheckMemberPointerConstantExpression(EvalInfo &Info, | 
|  | 2108 | SourceLocation Loc, | 
|  | 2109 | QualType Type, | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 2110 | const APValue &Value, | 
|  | 2111 | Expr::ConstExprUsage Usage) { | 
| Reid Kleckner | cd016d8 | 2017-07-07 22:04:29 +0000 | [diff] [blame] | 2112 | const ValueDecl *Member = Value.getMemberPointerDecl(); | 
|  | 2113 | const auto *FD = dyn_cast_or_null<CXXMethodDecl>(Member); | 
|  | 2114 | if (!FD) | 
|  | 2115 | return true; | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 2116 | return Usage == Expr::EvaluateForMangling || FD->isVirtual() || | 
|  | 2117 | !FD->hasAttr<DLLImportAttr>(); | 
| Reid Kleckner | cd016d8 | 2017-07-07 22:04:29 +0000 | [diff] [blame] | 2118 | } | 
|  | 2119 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 2120 | /// Check that this core constant expression is of literal type, and if not, | 
|  | 2121 | /// produce an appropriate diagnostic. | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 2122 | static bool CheckLiteralType(EvalInfo &Info, const Expr *E, | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 2123 | const LValue *This = nullptr) { | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 2124 | if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx)) | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 2125 | return true; | 
|  | 2126 |  | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 2127 | // C++1y: A constant initializer for an object o [...] may also invoke | 
|  | 2128 | // constexpr constructors for o and its subobjects even if those objects | 
|  | 2129 | // are of non-literal class types. | 
| David L. Jones | f55ce36 | 2017-01-09 21:38:07 +0000 | [diff] [blame] | 2130 | // | 
|  | 2131 | // C++11 missed this detail for aggregates, so classes like this: | 
|  | 2132 | //   struct foo_t { union { int i; volatile int j; } u; }; | 
|  | 2133 | // are not (obviously) initializable like so: | 
|  | 2134 | //   __attribute__((__require_constant_initialization__)) | 
|  | 2135 | //   static const foo_t x = {{0}}; | 
|  | 2136 | // because "i" is a subobject with non-literal initialization (due to the | 
|  | 2137 | // volatile member of the union). See: | 
|  | 2138 | //   http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677 | 
|  | 2139 | // Therefore, we use the C++1y behavior. | 
|  | 2140 | if (This && Info.EvaluatingDecl == This->getLValueBase()) | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 2141 | return true; | 
|  | 2142 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 2143 | // Prvalue constant expressions must be of literal types. | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 2144 | if (Info.getLangOpts().CPlusPlus11) | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2145 | Info.FFDiag(E, diag::note_constexpr_nonliteral) | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 2146 | << E->getType(); | 
|  | 2147 | else | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2148 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 2149 | return false; | 
|  | 2150 | } | 
|  | 2151 |  | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2152 | static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, | 
|  | 2153 | EvalInfo &Info, SourceLocation DiagLoc, | 
|  | 2154 | QualType Type, const APValue &Value, | 
|  | 2155 | Expr::ConstExprUsage Usage, | 
|  | 2156 | SourceLocation SubobjectLoc, | 
|  | 2157 | CheckedTemporaries &CheckedTemps) { | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 2158 | if (!Value.hasValue()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2159 | Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 2160 | << true << Type; | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 2161 | if (SubobjectLoc.isValid()) | 
|  | 2162 | Info.Note(SubobjectLoc, diag::note_constexpr_subobject_declared_here); | 
| Richard Smith | 1a90f59 | 2013-06-18 17:51:51 +0000 | [diff] [blame] | 2163 | return false; | 
|  | 2164 | } | 
|  | 2165 |  | 
| Richard Smith | 77be48a | 2014-07-31 06:31:19 +0000 | [diff] [blame] | 2166 | // We allow _Atomic(T) to be initialized from anything that T can be | 
|  | 2167 | // initialized from. | 
|  | 2168 | if (const AtomicType *AT = Type->getAs<AtomicType>()) | 
|  | 2169 | Type = AT->getValueType(); | 
|  | 2170 |  | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2171 | // Core issue 1454: For a literal constant expression of array or class type, | 
|  | 2172 | // each subobject of its value shall have been initialized by a constant | 
|  | 2173 | // expression. | 
|  | 2174 | if (Value.isArray()) { | 
|  | 2175 | QualType EltTy = Type->castAsArrayTypeUnsafe()->getElementType(); | 
|  | 2176 | for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) { | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2177 | if (!CheckEvaluationResult(CERK, Info, DiagLoc, EltTy, | 
|  | 2178 | Value.getArrayInitializedElt(I), Usage, | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2179 | SubobjectLoc, CheckedTemps)) | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2180 | return false; | 
|  | 2181 | } | 
|  | 2182 | if (!Value.hasArrayFiller()) | 
|  | 2183 | return true; | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2184 | return CheckEvaluationResult(CERK, Info, DiagLoc, EltTy, | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2185 | Value.getArrayFiller(), Usage, SubobjectLoc, | 
|  | 2186 | CheckedTemps); | 
| Richard Smith | 8081560 | 2011-11-07 05:07:52 +0000 | [diff] [blame] | 2187 | } | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2188 | if (Value.isUnion() && Value.getUnionField()) { | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2189 | return CheckEvaluationResult( | 
|  | 2190 | CERK, Info, DiagLoc, Value.getUnionField()->getType(), | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2191 | Value.getUnionValue(), Usage, Value.getUnionField()->getLocation(), | 
|  | 2192 | CheckedTemps); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2193 | } | 
|  | 2194 | if (Value.isStruct()) { | 
|  | 2195 | RecordDecl *RD = Type->castAs<RecordType>()->getDecl(); | 
|  | 2196 | if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) { | 
|  | 2197 | unsigned BaseIndex = 0; | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 2198 | for (const CXXBaseSpecifier &BS : CD->bases()) { | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2199 | if (!CheckEvaluationResult(CERK, Info, DiagLoc, BS.getType(), | 
|  | 2200 | Value.getStructBase(BaseIndex), Usage, | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2201 | BS.getBeginLoc(), CheckedTemps)) | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2202 | return false; | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 2203 | ++BaseIndex; | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2204 | } | 
|  | 2205 | } | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 2206 | for (const auto *I : RD->fields()) { | 
| Jordan Rose | d4503da | 2017-10-24 02:17:07 +0000 | [diff] [blame] | 2207 | if (I->isUnnamedBitfield()) | 
|  | 2208 | continue; | 
|  | 2209 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2210 | if (!CheckEvaluationResult(CERK, Info, DiagLoc, I->getType(), | 
|  | 2211 | Value.getStructField(I->getFieldIndex()), | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2212 | Usage, I->getLocation(), CheckedTemps)) | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2213 | return false; | 
|  | 2214 | } | 
|  | 2215 | } | 
|  | 2216 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2217 | if (Value.isLValue() && | 
|  | 2218 | CERK == CheckEvaluationResultKind::ConstantExpression) { | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2219 | LValue LVal; | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 2220 | LVal.setFrom(Info.Ctx, Value); | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2221 | return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal, Usage, | 
|  | 2222 | CheckedTemps); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2223 | } | 
|  | 2224 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2225 | if (Value.isMemberPointer() && | 
|  | 2226 | CERK == CheckEvaluationResultKind::ConstantExpression) | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 2227 | return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value, Usage); | 
| Reid Kleckner | cd016d8 | 2017-07-07 22:04:29 +0000 | [diff] [blame] | 2228 |  | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 2229 | // Everything else is fine. | 
|  | 2230 | return true; | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 2231 | } | 
|  | 2232 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2233 | /// Check that this core constant expression value is a valid value for a | 
|  | 2234 | /// constant expression. If not, report an appropriate diagnostic. Does not | 
|  | 2235 | /// check that the expression is of literal type. | 
|  | 2236 | static bool | 
|  | 2237 | CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, QualType Type, | 
|  | 2238 | const APValue &Value, | 
|  | 2239 | Expr::ConstExprUsage Usage = Expr::EvaluateForCodeGen) { | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2240 | CheckedTemporaries CheckedTemps; | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2241 | return CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression, | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2242 | Info, DiagLoc, Type, Value, Usage, | 
|  | 2243 | SourceLocation(), CheckedTemps); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2244 | } | 
|  | 2245 |  | 
|  | 2246 | /// Check that this evaluated value is fully-initialized and can be loaded by | 
|  | 2247 | /// an lvalue-to-rvalue conversion. | 
|  | 2248 | static bool CheckFullyInitialized(EvalInfo &Info, SourceLocation DiagLoc, | 
|  | 2249 | QualType Type, const APValue &Value) { | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 2250 | CheckedTemporaries CheckedTemps; | 
|  | 2251 | return CheckEvaluationResult( | 
|  | 2252 | CheckEvaluationResultKind::FullyInitialized, Info, DiagLoc, Type, Value, | 
|  | 2253 | Expr::EvaluateForCodeGen, SourceLocation(), CheckedTemps); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 2254 | } | 
|  | 2255 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 2256 | /// Enforce C++2a [expr.const]/4.17, which disallows new-expressions unless | 
|  | 2257 | /// "the allocated storage is deallocated within the evaluation". | 
|  | 2258 | static bool CheckMemoryLeaks(EvalInfo &Info) { | 
|  | 2259 | if (!Info.HeapAllocs.empty()) { | 
|  | 2260 | // We can still fold to a constant despite a compile-time memory leak, | 
|  | 2261 | // so long as the heap allocation isn't referenced in the result (we check | 
|  | 2262 | // that in CheckConstantExpression). | 
|  | 2263 | Info.CCEDiag(Info.HeapAllocs.begin()->second.AllocExpr, | 
|  | 2264 | diag::note_constexpr_memory_leak) | 
|  | 2265 | << unsigned(Info.HeapAllocs.size() - 1); | 
|  | 2266 | } | 
|  | 2267 | return true; | 
|  | 2268 | } | 
|  | 2269 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 2270 | static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) { | 
| John McCall | eb3e4f3 | 2010-05-07 21:34:32 +0000 | [diff] [blame] | 2271 | // A null base expression indicates a null pointer.  These are always | 
|  | 2272 | // evaluatable, and they are false unless the offset is zero. | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2273 | if (!Value.getLValueBase()) { | 
|  | 2274 | Result = !Value.getLValueOffset().isZero(); | 
| John McCall | eb3e4f3 | 2010-05-07 21:34:32 +0000 | [diff] [blame] | 2275 | return true; | 
|  | 2276 | } | 
| Rafael Espindola | a1f9cc1 | 2010-05-07 15:18:43 +0000 | [diff] [blame] | 2277 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2278 | // We have a non-null base.  These are generally known to be true, but if it's | 
|  | 2279 | // a weak declaration it can be null at runtime. | 
| John McCall | eb3e4f3 | 2010-05-07 21:34:32 +0000 | [diff] [blame] | 2280 | Result = true; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2281 | const ValueDecl *Decl = Value.getLValueBase().dyn_cast<const ValueDecl*>(); | 
| Lang Hames | d42bb47 | 2011-12-05 20:16:26 +0000 | [diff] [blame] | 2282 | return !Decl || !Decl->isWeak(); | 
| Eli Friedman | 334046a | 2009-06-14 02:17:33 +0000 | [diff] [blame] | 2283 | } | 
|  | 2284 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 2285 | static bool HandleConversionToBool(const APValue &Val, bool &Result) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2286 | switch (Val.getKind()) { | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 2287 | case APValue::None: | 
|  | 2288 | case APValue::Indeterminate: | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2289 | return false; | 
|  | 2290 | case APValue::Int: | 
|  | 2291 | Result = Val.getInt().getBoolValue(); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 2292 | return true; | 
| Leonard Chan | 86285d2 | 2019-01-16 18:53:05 +0000 | [diff] [blame] | 2293 | case APValue::FixedPoint: | 
|  | 2294 | Result = Val.getFixedPoint().getBoolValue(); | 
|  | 2295 | return true; | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2296 | case APValue::Float: | 
|  | 2297 | Result = !Val.getFloat().isZero(); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 2298 | return true; | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2299 | case APValue::ComplexInt: | 
|  | 2300 | Result = Val.getComplexIntReal().getBoolValue() || | 
|  | 2301 | Val.getComplexIntImag().getBoolValue(); | 
|  | 2302 | return true; | 
|  | 2303 | case APValue::ComplexFloat: | 
|  | 2304 | Result = !Val.getComplexFloatReal().isZero() || | 
|  | 2305 | !Val.getComplexFloatImag().isZero(); | 
|  | 2306 | return true; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2307 | case APValue::LValue: | 
|  | 2308 | return EvalPointerValueAsBool(Val, Result); | 
|  | 2309 | case APValue::MemberPointer: | 
|  | 2310 | Result = Val.getMemberPointerDecl(); | 
|  | 2311 | return true; | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2312 | case APValue::Vector: | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 2313 | case APValue::Array: | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2314 | case APValue::Struct: | 
|  | 2315 | case APValue::Union: | 
| Eli Friedman | fd5e54d | 2012-01-04 23:13:47 +0000 | [diff] [blame] | 2316 | case APValue::AddrLabelDiff: | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2317 | return false; | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 2318 | } | 
|  | 2319 |  | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2320 | llvm_unreachable("unknown APValue kind"); | 
|  | 2321 | } | 
|  | 2322 |  | 
|  | 2323 | static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result, | 
|  | 2324 | EvalInfo &Info) { | 
|  | 2325 | assert(E->isRValue() && "missing lvalue-to-rvalue conv in bool condition"); | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 2326 | APValue Val; | 
| Argyrios Kyrtzidis | 91d0098 | 2012-02-27 20:21:34 +0000 | [diff] [blame] | 2327 | if (!Evaluate(Val, Info, E)) | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2328 | return false; | 
| Argyrios Kyrtzidis | 91d0098 | 2012-02-27 20:21:34 +0000 | [diff] [blame] | 2329 | return HandleConversionToBool(Val, Result); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 2330 | } | 
|  | 2331 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2332 | template<typename T> | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2333 | static bool HandleOverflow(EvalInfo &Info, const Expr *E, | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2334 | const T &SrcValue, QualType DestType) { | 
| Eli Friedman | 4eafb6b | 2012-07-17 21:03:05 +0000 | [diff] [blame] | 2335 | Info.CCEDiag(E, diag::note_constexpr_overflow) | 
| Richard Smith | fe80003 | 2012-01-31 04:08:20 +0000 | [diff] [blame] | 2336 | << SrcValue << DestType; | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 2337 | return Info.noteUndefinedBehavior(); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2338 | } | 
|  | 2339 |  | 
|  | 2340 | static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E, | 
|  | 2341 | QualType SrcType, const APFloat &Value, | 
|  | 2342 | QualType DestType, APSInt &Result) { | 
|  | 2343 | unsigned DestWidth = Info.Ctx.getIntWidth(DestType); | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 2344 | // Determine whether we are converting to unsigned or signed. | 
| Douglas Gregor | 6ab2fa8 | 2011-05-20 16:38:50 +0000 | [diff] [blame] | 2345 | bool DestSigned = DestType->isSignedIntegerOrEnumerationType(); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2346 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2347 | Result = APSInt(DestWidth, !DestSigned); | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 2348 | bool ignored; | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2349 | if (Value.convertToInteger(Result, llvm::APFloat::rmTowardZero, &ignored) | 
|  | 2350 | & APFloat::opInvalidOp) | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2351 | return HandleOverflow(Info, E, Value, DestType); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2352 | return true; | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 2353 | } | 
|  | 2354 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2355 | static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, | 
|  | 2356 | QualType SrcType, QualType DestType, | 
|  | 2357 | APFloat &Result) { | 
|  | 2358 | APFloat Value = Result; | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 2359 | bool ignored; | 
| Richard Smith | 9e52c43 | 2019-07-06 21:05:52 +0000 | [diff] [blame] | 2360 | Result.convert(Info.Ctx.getFloatTypeSemantics(DestType), | 
|  | 2361 | APFloat::rmNearestTiesToEven, &ignored); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2362 | return true; | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 2363 | } | 
|  | 2364 |  | 
| Richard Smith | 911e142 | 2012-01-30 22:27:01 +0000 | [diff] [blame] | 2365 | static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E, | 
|  | 2366 | QualType DestType, QualType SrcType, | 
| George Burgess IV | 533ff00 | 2015-12-11 00:23:35 +0000 | [diff] [blame] | 2367 | const APSInt &Value) { | 
| Richard Smith | 911e142 | 2012-01-30 22:27:01 +0000 | [diff] [blame] | 2368 | unsigned DestWidth = Info.Ctx.getIntWidth(DestType); | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 2369 | // Figure out if this is a truncate, extend or noop cast. | 
|  | 2370 | // If the input is signed, do a sign extend, noop, or truncate. | 
| Richard Smith | bd844e0 | 2018-11-12 20:11:57 +0000 | [diff] [blame] | 2371 | APSInt Result = Value.extOrTrunc(DestWidth); | 
| Douglas Gregor | 6ab2fa8 | 2011-05-20 16:38:50 +0000 | [diff] [blame] | 2372 | Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType()); | 
| Richard Smith | bd844e0 | 2018-11-12 20:11:57 +0000 | [diff] [blame] | 2373 | if (DestType->isBooleanType()) | 
|  | 2374 | Result = Value.getBoolValue(); | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 2375 | return Result; | 
|  | 2376 | } | 
|  | 2377 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2378 | static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E, | 
|  | 2379 | QualType SrcType, const APSInt &Value, | 
|  | 2380 | QualType DestType, APFloat &Result) { | 
|  | 2381 | Result = APFloat(Info.Ctx.getFloatTypeSemantics(DestType), 1); | 
| Richard Smith | 9e52c43 | 2019-07-06 21:05:52 +0000 | [diff] [blame] | 2382 | Result.convertFromAPInt(Value, Value.isSigned(), | 
|  | 2383 | APFloat::rmNearestTiesToEven); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 2384 | return true; | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 2385 | } | 
|  | 2386 |  | 
| Richard Smith | 49ca8aa | 2013-08-06 07:09:20 +0000 | [diff] [blame] | 2387 | static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E, | 
|  | 2388 | APValue &Value, const FieldDecl *FD) { | 
|  | 2389 | assert(FD->isBitField() && "truncateBitfieldValue on non-bitfield"); | 
|  | 2390 |  | 
|  | 2391 | if (!Value.isInt()) { | 
|  | 2392 | // Trying to store a pointer-cast-to-integer into a bitfield. | 
|  | 2393 | // FIXME: In this case, we should provide the diagnostic for casting | 
|  | 2394 | // a pointer to an integer. | 
|  | 2395 | assert(Value.isLValue() && "integral value neither int nor lvalue?"); | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2396 | Info.FFDiag(E); | 
| Richard Smith | 49ca8aa | 2013-08-06 07:09:20 +0000 | [diff] [blame] | 2397 | return false; | 
|  | 2398 | } | 
|  | 2399 |  | 
|  | 2400 | APSInt &Int = Value.getInt(); | 
|  | 2401 | unsigned OldBitWidth = Int.getBitWidth(); | 
|  | 2402 | unsigned NewBitWidth = FD->getBitWidthValue(Info.Ctx); | 
|  | 2403 | if (NewBitWidth < OldBitWidth) | 
|  | 2404 | Int = Int.trunc(NewBitWidth).extend(OldBitWidth); | 
|  | 2405 | return true; | 
|  | 2406 | } | 
|  | 2407 |  | 
| Eli Friedman | 803acb3 | 2011-12-22 03:51:45 +0000 | [diff] [blame] | 2408 | static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, | 
|  | 2409 | llvm::APInt &Res) { | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 2410 | APValue SVal; | 
| Eli Friedman | 803acb3 | 2011-12-22 03:51:45 +0000 | [diff] [blame] | 2411 | if (!Evaluate(SVal, Info, E)) | 
|  | 2412 | return false; | 
|  | 2413 | if (SVal.isInt()) { | 
|  | 2414 | Res = SVal.getInt(); | 
|  | 2415 | return true; | 
|  | 2416 | } | 
|  | 2417 | if (SVal.isFloat()) { | 
|  | 2418 | Res = SVal.getFloat().bitcastToAPInt(); | 
|  | 2419 | return true; | 
|  | 2420 | } | 
|  | 2421 | if (SVal.isVector()) { | 
|  | 2422 | QualType VecTy = E->getType(); | 
|  | 2423 | unsigned VecSize = Info.Ctx.getTypeSize(VecTy); | 
|  | 2424 | QualType EltTy = VecTy->castAs<VectorType>()->getElementType(); | 
|  | 2425 | unsigned EltSize = Info.Ctx.getTypeSize(EltTy); | 
|  | 2426 | bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); | 
|  | 2427 | Res = llvm::APInt::getNullValue(VecSize); | 
|  | 2428 | for (unsigned i = 0; i < SVal.getVectorLength(); i++) { | 
|  | 2429 | APValue &Elt = SVal.getVectorElt(i); | 
|  | 2430 | llvm::APInt EltAsInt; | 
|  | 2431 | if (Elt.isInt()) { | 
|  | 2432 | EltAsInt = Elt.getInt(); | 
|  | 2433 | } else if (Elt.isFloat()) { | 
|  | 2434 | EltAsInt = Elt.getFloat().bitcastToAPInt(); | 
|  | 2435 | } else { | 
|  | 2436 | // Don't try to handle vectors of anything other than int or float | 
|  | 2437 | // (not sure if it's possible to hit this case). | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2438 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Eli Friedman | 803acb3 | 2011-12-22 03:51:45 +0000 | [diff] [blame] | 2439 | return false; | 
|  | 2440 | } | 
|  | 2441 | unsigned BaseEltSize = EltAsInt.getBitWidth(); | 
|  | 2442 | if (BigEndian) | 
|  | 2443 | Res |= EltAsInt.zextOrTrunc(VecSize).rotr(i*EltSize+BaseEltSize); | 
|  | 2444 | else | 
|  | 2445 | Res |= EltAsInt.zextOrTrunc(VecSize).rotl(i*EltSize); | 
|  | 2446 | } | 
|  | 2447 | return true; | 
|  | 2448 | } | 
|  | 2449 | // Give up if the input isn't an int, float, or vector.  For example, we | 
|  | 2450 | // reject "(v4i16)(intptr_t)&a". | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2451 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Eli Friedman | 803acb3 | 2011-12-22 03:51:45 +0000 | [diff] [blame] | 2452 | return false; | 
|  | 2453 | } | 
|  | 2454 |  | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2455 | /// Perform the given integer operation, which is known to need at most BitWidth | 
|  | 2456 | /// bits, and check for overflow in the original type (if that type was not an | 
|  | 2457 | /// unsigned type). | 
|  | 2458 | template<typename Operation> | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2459 | static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E, | 
|  | 2460 | const APSInt &LHS, const APSInt &RHS, | 
|  | 2461 | unsigned BitWidth, Operation Op, | 
|  | 2462 | APSInt &Result) { | 
|  | 2463 | if (LHS.isUnsigned()) { | 
|  | 2464 | Result = Op(LHS, RHS); | 
|  | 2465 | return true; | 
|  | 2466 | } | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2467 |  | 
|  | 2468 | APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2469 | Result = Value.trunc(LHS.getBitWidth()); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2470 | if (Result.extend(BitWidth) != Value) { | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 2471 | if (Info.checkingForUndefinedBehavior()) | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2472 | Info.Ctx.getDiagnostics().Report(E->getExprLoc(), | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2473 | diag::warn_integer_constant_overflow) | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2474 | << Result.toString(10) << E->getType(); | 
|  | 2475 | else | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2476 | return HandleOverflow(Info, E, Value, E->getType()); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2477 | } | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2478 | return true; | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2479 | } | 
|  | 2480 |  | 
|  | 2481 | /// Perform the given binary integer operation. | 
|  | 2482 | static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, | 
|  | 2483 | BinaryOperatorKind Opcode, APSInt RHS, | 
|  | 2484 | APSInt &Result) { | 
|  | 2485 | switch (Opcode) { | 
|  | 2486 | default: | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2487 | Info.FFDiag(E); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2488 | return false; | 
|  | 2489 | case BO_Mul: | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2490 | return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2, | 
|  | 2491 | std::multiplies<APSInt>(), Result); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2492 | case BO_Add: | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2493 | return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, | 
|  | 2494 | std::plus<APSInt>(), Result); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2495 | case BO_Sub: | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2496 | return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, | 
|  | 2497 | std::minus<APSInt>(), Result); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2498 | case BO_And: Result = LHS & RHS; return true; | 
|  | 2499 | case BO_Xor: Result = LHS ^ RHS; return true; | 
|  | 2500 | case BO_Or:  Result = LHS | RHS; return true; | 
|  | 2501 | case BO_Div: | 
|  | 2502 | case BO_Rem: | 
|  | 2503 | if (RHS == 0) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2504 | Info.FFDiag(E, diag::note_expr_divide_by_zero); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2505 | return false; | 
|  | 2506 | } | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2507 | Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); | 
|  | 2508 | // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. APSInt supports | 
|  | 2509 | // this operation and gives the two's complement result. | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2510 | if (RHS.isNegative() && RHS.isAllOnesValue() && | 
|  | 2511 | LHS.isSigned() && LHS.isMinSignedValue()) | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2512 | return HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), | 
|  | 2513 | E->getType()); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2514 | return true; | 
|  | 2515 | case BO_Shl: { | 
|  | 2516 | if (Info.getLangOpts().OpenCL) | 
|  | 2517 | // OpenCL 6.3j: shift values are effectively % word size of LHS. | 
|  | 2518 | RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), | 
|  | 2519 | static_cast<uint64_t>(LHS.getBitWidth() - 1)), | 
|  | 2520 | RHS.isUnsigned()); | 
|  | 2521 | else if (RHS.isSigned() && RHS.isNegative()) { | 
|  | 2522 | // During constant-folding, a negative shift is an opposite shift. Such | 
|  | 2523 | // a shift is not a constant expression. | 
|  | 2524 | Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; | 
|  | 2525 | RHS = -RHS; | 
|  | 2526 | goto shift_right; | 
|  | 2527 | } | 
|  | 2528 | shift_left: | 
|  | 2529 | // C++11 [expr.shift]p1: Shift width must be less than the bit width of | 
|  | 2530 | // the shifted type. | 
|  | 2531 | unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); | 
|  | 2532 | if (SA != RHS) { | 
|  | 2533 | Info.CCEDiag(E, diag::note_constexpr_large_shift) | 
|  | 2534 | << RHS << E->getType() << LHS.getBitWidth(); | 
| Richard Smith | 7939ba0 | 2019-06-25 01:45:26 +0000 | [diff] [blame] | 2535 | } else if (LHS.isSigned() && !Info.getLangOpts().CPlusPlus2a) { | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2536 | // C++11 [expr.shift]p2: A signed left shift must have a non-negative | 
|  | 2537 | // operand, and must not overflow the corresponding unsigned type. | 
| Richard Smith | 7939ba0 | 2019-06-25 01:45:26 +0000 | [diff] [blame] | 2538 | // C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to | 
|  | 2539 | // E1 x 2^E2 module 2^N. | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2540 | if (LHS.isNegative()) | 
|  | 2541 | Info.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS; | 
|  | 2542 | else if (LHS.countLeadingZeros() < SA) | 
|  | 2543 | Info.CCEDiag(E, diag::note_constexpr_lshift_discards); | 
|  | 2544 | } | 
|  | 2545 | Result = LHS << SA; | 
|  | 2546 | return true; | 
|  | 2547 | } | 
|  | 2548 | case BO_Shr: { | 
|  | 2549 | if (Info.getLangOpts().OpenCL) | 
|  | 2550 | // OpenCL 6.3j: shift values are effectively % word size of LHS. | 
|  | 2551 | RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), | 
|  | 2552 | static_cast<uint64_t>(LHS.getBitWidth() - 1)), | 
|  | 2553 | RHS.isUnsigned()); | 
|  | 2554 | else if (RHS.isSigned() && RHS.isNegative()) { | 
|  | 2555 | // During constant-folding, a negative shift is an opposite shift. Such a | 
|  | 2556 | // shift is not a constant expression. | 
|  | 2557 | Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; | 
|  | 2558 | RHS = -RHS; | 
|  | 2559 | goto shift_left; | 
|  | 2560 | } | 
|  | 2561 | shift_right: | 
|  | 2562 | // C++11 [expr.shift]p1: Shift width must be less than the bit width of the | 
|  | 2563 | // shifted type. | 
|  | 2564 | unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); | 
|  | 2565 | if (SA != RHS) | 
|  | 2566 | Info.CCEDiag(E, diag::note_constexpr_large_shift) | 
|  | 2567 | << RHS << E->getType() << LHS.getBitWidth(); | 
|  | 2568 | Result = LHS >> SA; | 
|  | 2569 | return true; | 
|  | 2570 | } | 
|  | 2571 |  | 
|  | 2572 | case BO_LT: Result = LHS < RHS; return true; | 
|  | 2573 | case BO_GT: Result = LHS > RHS; return true; | 
|  | 2574 | case BO_LE: Result = LHS <= RHS; return true; | 
|  | 2575 | case BO_GE: Result = LHS >= RHS; return true; | 
|  | 2576 | case BO_EQ: Result = LHS == RHS; return true; | 
|  | 2577 | case BO_NE: Result = LHS != RHS; return true; | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 2578 | case BO_Cmp: | 
|  | 2579 | llvm_unreachable("BO_Cmp should be handled elsewhere"); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 2580 | } | 
|  | 2581 | } | 
|  | 2582 |  | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 2583 | /// Perform the given binary floating-point operation, in-place, on LHS. | 
|  | 2584 | static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E, | 
|  | 2585 | APFloat &LHS, BinaryOperatorKind Opcode, | 
|  | 2586 | const APFloat &RHS) { | 
|  | 2587 | switch (Opcode) { | 
|  | 2588 | default: | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2589 | Info.FFDiag(E); | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 2590 | return false; | 
|  | 2591 | case BO_Mul: | 
|  | 2592 | LHS.multiply(RHS, APFloat::rmNearestTiesToEven); | 
|  | 2593 | break; | 
|  | 2594 | case BO_Add: | 
|  | 2595 | LHS.add(RHS, APFloat::rmNearestTiesToEven); | 
|  | 2596 | break; | 
|  | 2597 | case BO_Sub: | 
|  | 2598 | LHS.subtract(RHS, APFloat::rmNearestTiesToEven); | 
|  | 2599 | break; | 
|  | 2600 | case BO_Div: | 
| Richard Smith | 9e52c43 | 2019-07-06 21:05:52 +0000 | [diff] [blame] | 2601 | // [expr.mul]p4: | 
|  | 2602 | //   If the second operand of / or % is zero the behavior is undefined. | 
|  | 2603 | if (RHS.isZero()) | 
|  | 2604 | Info.CCEDiag(E, diag::note_expr_divide_by_zero); | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 2605 | LHS.divide(RHS, APFloat::rmNearestTiesToEven); | 
|  | 2606 | break; | 
|  | 2607 | } | 
|  | 2608 |  | 
| Richard Smith | 9e52c43 | 2019-07-06 21:05:52 +0000 | [diff] [blame] | 2609 | // [expr.pre]p4: | 
|  | 2610 | //   If during the evaluation of an expression, the result is not | 
|  | 2611 | //   mathematically defined [...], the behavior is undefined. | 
|  | 2612 | // FIXME: C++ rules require us to not conform to IEEE 754 here. | 
|  | 2613 | if (LHS.isNaN()) { | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 2614 | Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 2615 | return Info.noteUndefinedBehavior(); | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 2616 | } | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 2617 | return true; | 
|  | 2618 | } | 
|  | 2619 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2620 | /// Cast an lvalue referring to a base subobject to a derived class, by | 
|  | 2621 | /// truncating the lvalue's path to the given length. | 
|  | 2622 | static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result, | 
|  | 2623 | const RecordDecl *TruncatedType, | 
|  | 2624 | unsigned TruncatedElements) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2625 | SubobjectDesignator &D = Result.Designator; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2626 |  | 
|  | 2627 | // Check we actually point to a derived class object. | 
|  | 2628 | if (TruncatedElements == D.Entries.size()) | 
|  | 2629 | return true; | 
|  | 2630 | assert(TruncatedElements >= D.MostDerivedPathLength && | 
|  | 2631 | "not casting to a derived class"); | 
|  | 2632 | if (!Result.checkSubobject(Info, E, CSK_Derived)) | 
|  | 2633 | return false; | 
|  | 2634 |  | 
|  | 2635 | // Truncate the path to the subobject, and remove any derived-to-base offsets. | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2636 | const RecordDecl *RD = TruncatedType; | 
|  | 2637 | for (unsigned I = TruncatedElements, N = D.Entries.size(); I != N; ++I) { | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2638 | if (RD->isInvalidDecl()) return false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2639 | const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); | 
|  | 2640 | const CXXRecordDecl *Base = getAsBaseClass(D.Entries[I]); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2641 | if (isVirtualBaseClass(D.Entries[I])) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2642 | Result.Offset -= Layout.getVBaseClassOffset(Base); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2643 | else | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2644 | Result.Offset -= Layout.getBaseClassOffset(Base); | 
|  | 2645 | RD = Base; | 
|  | 2646 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 2647 | D.Entries.resize(TruncatedElements); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2648 | return true; | 
|  | 2649 | } | 
|  | 2650 |  | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2651 | static bool HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj, | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2652 | const CXXRecordDecl *Derived, | 
|  | 2653 | const CXXRecordDecl *Base, | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 2654 | const ASTRecordLayout *RL = nullptr) { | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2655 | if (!RL) { | 
|  | 2656 | if (Derived->isInvalidDecl()) return false; | 
|  | 2657 | RL = &Info.Ctx.getASTRecordLayout(Derived); | 
|  | 2658 | } | 
|  | 2659 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2660 | Obj.getLValueOffset() += RL->getBaseClassOffset(Base); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2661 | Obj.addDecl(Info, E, Base, /*Virtual*/ false); | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2662 | return true; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2663 | } | 
|  | 2664 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2665 | static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2666 | const CXXRecordDecl *DerivedDecl, | 
|  | 2667 | const CXXBaseSpecifier *Base) { | 
|  | 2668 | const CXXRecordDecl *BaseDecl = Base->getType()->getAsCXXRecordDecl(); | 
|  | 2669 |  | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2670 | if (!Base->isVirtual()) | 
|  | 2671 | return HandleLValueDirectBase(Info, E, Obj, DerivedDecl, BaseDecl); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2672 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2673 | SubobjectDesignator &D = Obj.Designator; | 
|  | 2674 | if (D.Invalid) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2675 | return false; | 
|  | 2676 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2677 | // Extract most-derived object and corresponding type. | 
|  | 2678 | DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); | 
|  | 2679 | if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) | 
|  | 2680 | return false; | 
|  | 2681 |  | 
|  | 2682 | // Find the virtual base class. | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2683 | if (DerivedDecl->isInvalidDecl()) return false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2684 | const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(DerivedDecl); | 
|  | 2685 | Obj.getLValueOffset() += Layout.getVBaseClassOffset(BaseDecl); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2686 | Obj.addDecl(Info, E, BaseDecl, /*Virtual*/ true); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2687 | return true; | 
|  | 2688 | } | 
|  | 2689 |  | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 2690 | static bool HandleLValueBasePath(EvalInfo &Info, const CastExpr *E, | 
|  | 2691 | QualType Type, LValue &Result) { | 
|  | 2692 | for (CastExpr::path_const_iterator PathI = E->path_begin(), | 
|  | 2693 | PathE = E->path_end(); | 
|  | 2694 | PathI != PathE; ++PathI) { | 
|  | 2695 | if (!HandleLValueBase(Info, E, Result, Type->getAsCXXRecordDecl(), | 
|  | 2696 | *PathI)) | 
|  | 2697 | return false; | 
|  | 2698 | Type = (*PathI)->getType(); | 
|  | 2699 | } | 
|  | 2700 | return true; | 
|  | 2701 | } | 
|  | 2702 |  | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 2703 | /// Cast an lvalue referring to a derived class to a known base subobject. | 
|  | 2704 | static bool CastToBaseClass(EvalInfo &Info, const Expr *E, LValue &Result, | 
|  | 2705 | const CXXRecordDecl *DerivedRD, | 
|  | 2706 | const CXXRecordDecl *BaseRD) { | 
|  | 2707 | CXXBasePaths Paths(/*FindAmbiguities=*/false, | 
|  | 2708 | /*RecordPaths=*/true, /*DetectVirtual=*/false); | 
|  | 2709 | if (!DerivedRD->isDerivedFrom(BaseRD, Paths)) | 
|  | 2710 | llvm_unreachable("Class must be derived from the passed in base class!"); | 
|  | 2711 |  | 
|  | 2712 | for (CXXBasePathElement &Elem : Paths.front()) | 
|  | 2713 | if (!HandleLValueBase(Info, E, Result, Elem.Class, Elem.Base)) | 
|  | 2714 | return false; | 
|  | 2715 | return true; | 
|  | 2716 | } | 
|  | 2717 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2718 | /// Update LVal to refer to the given field, which must be a member of the type | 
|  | 2719 | /// currently described by LVal. | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2720 | static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2721 | const FieldDecl *FD, | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 2722 | const ASTRecordLayout *RL = nullptr) { | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2723 | if (!RL) { | 
|  | 2724 | if (FD->getParent()->isInvalidDecl()) return false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2725 | RL = &Info.Ctx.getASTRecordLayout(FD->getParent()); | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2726 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2727 |  | 
|  | 2728 | unsigned I = FD->getFieldIndex(); | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 2729 | LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I))); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2730 | LVal.addDecl(Info, E, FD); | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2731 | return true; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2732 | } | 
|  | 2733 |  | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 2734 | /// Update LVal to refer to the given indirect field. | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2735 | static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E, | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 2736 | LValue &LVal, | 
|  | 2737 | const IndirectFieldDecl *IFD) { | 
| Aaron Ballman | 29c9460 | 2014-03-07 18:36:15 +0000 | [diff] [blame] | 2738 | for (const auto *C : IFD->chain()) | 
| Aaron Ballman | 1391608 | 2014-03-07 18:11:58 +0000 | [diff] [blame] | 2739 | if (!HandleLValueMember(Info, E, LVal, cast<FieldDecl>(C))) | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 2740 | return false; | 
|  | 2741 | return true; | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 2742 | } | 
|  | 2743 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2744 | /// Get the size of the given type in char units. | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 2745 | static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, | 
|  | 2746 | QualType Type, CharUnits &Size) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2747 | // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc | 
|  | 2748 | // extension. | 
|  | 2749 | if (Type->isVoidType() || Type->isFunctionType()) { | 
|  | 2750 | Size = CharUnits::One(); | 
|  | 2751 | return true; | 
|  | 2752 | } | 
|  | 2753 |  | 
| Saleem Abdulrasool | ada78fe | 2016-06-04 03:16:21 +0000 | [diff] [blame] | 2754 | if (Type->isDependentType()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2755 | Info.FFDiag(Loc); | 
| Saleem Abdulrasool | ada78fe | 2016-06-04 03:16:21 +0000 | [diff] [blame] | 2756 | return false; | 
|  | 2757 | } | 
|  | 2758 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2759 | if (!Type->isConstantSizeType()) { | 
|  | 2760 | // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 2761 | // FIXME: Better diagnostic. | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2762 | Info.FFDiag(Loc); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2763 | return false; | 
|  | 2764 | } | 
|  | 2765 |  | 
|  | 2766 | Size = Info.Ctx.getTypeSizeInChars(Type); | 
|  | 2767 | return true; | 
|  | 2768 | } | 
|  | 2769 |  | 
|  | 2770 | /// Update a pointer value to model pointer arithmetic. | 
|  | 2771 | /// \param Info - Information about the ongoing evaluation. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2772 | /// \param E - The expression being evaluated, for diagnostic purposes. | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2773 | /// \param LVal - The pointer value to be updated. | 
|  | 2774 | /// \param EltTy - The pointee type represented by LVal. | 
|  | 2775 | /// \param Adjustment - The adjustment, in objects of type EltTy, to add. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 2776 | static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, | 
|  | 2777 | LValue &LVal, QualType EltTy, | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 2778 | APSInt Adjustment) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2779 | CharUnits SizeOfPointee; | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 2780 | if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee)) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2781 | return false; | 
|  | 2782 |  | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 2783 | LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2784 | return true; | 
|  | 2785 | } | 
|  | 2786 |  | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 2787 | static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, | 
|  | 2788 | LValue &LVal, QualType EltTy, | 
|  | 2789 | int64_t Adjustment) { | 
|  | 2790 | return HandleLValueArrayAdjustment(Info, E, LVal, EltTy, | 
|  | 2791 | APSInt::get(Adjustment)); | 
|  | 2792 | } | 
|  | 2793 |  | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 2794 | /// Update an lvalue to refer to a component of a complex number. | 
|  | 2795 | /// \param Info - Information about the ongoing evaluation. | 
|  | 2796 | /// \param LVal - The lvalue to be updated. | 
|  | 2797 | /// \param EltTy - The complex number's component type. | 
|  | 2798 | /// \param Imag - False for the real component, true for the imaginary. | 
|  | 2799 | static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, | 
|  | 2800 | LValue &LVal, QualType EltTy, | 
|  | 2801 | bool Imag) { | 
|  | 2802 | if (Imag) { | 
|  | 2803 | CharUnits SizeOfComponent; | 
|  | 2804 | if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfComponent)) | 
|  | 2805 | return false; | 
|  | 2806 | LVal.Offset += SizeOfComponent; | 
|  | 2807 | } | 
|  | 2808 | LVal.addComplex(Info, E, EltTy, Imag); | 
|  | 2809 | return true; | 
|  | 2810 | } | 
|  | 2811 |  | 
| Richard Smith | 2790870 | 2011-10-24 17:54:18 +0000 | [diff] [blame] | 2812 | /// Try to evaluate the initializer for a variable declaration. | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 2813 | /// | 
|  | 2814 | /// \param Info   Information about the ongoing evaluation. | 
|  | 2815 | /// \param E      An expression to be used when printing diagnostics. | 
|  | 2816 | /// \param VD     The variable whose initializer should be obtained. | 
|  | 2817 | /// \param Frame  The frame in which the variable was created. Must be null | 
|  | 2818 | ///               if this variable is not local to the evaluation. | 
|  | 2819 | /// \param Result Filled in with a pointer to the value of the variable. | 
|  | 2820 | static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, | 
|  | 2821 | const VarDecl *VD, CallStackFrame *Frame, | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 2822 | APValue *&Result, const LValue *LVal) { | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 2823 |  | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 2824 | // If this is a parameter to an active constexpr function call, perform | 
|  | 2825 | // argument substitution. | 
|  | 2826 | if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD)) { | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 2827 | // Assume arguments of a potential constant expression are unknown | 
|  | 2828 | // constant expressions. | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 2829 | if (Info.checkingPotentialConstantExpression()) | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 2830 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 2831 | if (!Frame || !Frame->Arguments) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2832 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Richard Smith | fec0992 | 2011-11-01 16:57:24 +0000 | [diff] [blame] | 2833 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 2834 | } | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 2835 | Result = &Frame->Arguments[PVD->getFunctionScopeIndex()]; | 
| Richard Smith | fec0992 | 2011-11-01 16:57:24 +0000 | [diff] [blame] | 2836 | return true; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 2837 | } | 
| Richard Smith | 2790870 | 2011-10-24 17:54:18 +0000 | [diff] [blame] | 2838 |  | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 2839 | // If this is a local variable, dig out its value. | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 2840 | if (Frame) { | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 2841 | Result = LVal ? Frame->getTemporary(VD, LVal->getLValueVersion()) | 
|  | 2842 | : Frame->getCurrentTemporary(VD); | 
| Faisal Vali | a734ab9 | 2016-03-26 16:11:37 +0000 | [diff] [blame] | 2843 | if (!Result) { | 
|  | 2844 | // Assume variables referenced within a lambda's call operator that were | 
|  | 2845 | // not declared within the call operator are captures and during checking | 
|  | 2846 | // of a potential constant expression, assume they are unknown constant | 
|  | 2847 | // expressions. | 
|  | 2848 | assert(isLambdaCallOperator(Frame->Callee) && | 
|  | 2849 | (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) && | 
|  | 2850 | "missing value for local variable"); | 
|  | 2851 | if (Info.checkingPotentialConstantExpression()) | 
|  | 2852 | return false; | 
|  | 2853 | // FIXME: implement capture evaluation during constant expr evaluation. | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 2854 | Info.FFDiag(E->getBeginLoc(), | 
|  | 2855 | diag::note_unimplemented_constexpr_lambda_feature_ast) | 
| Faisal Vali | a734ab9 | 2016-03-26 16:11:37 +0000 | [diff] [blame] | 2856 | << "captures not currently allowed"; | 
|  | 2857 | return false; | 
|  | 2858 | } | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 2859 | return true; | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 2860 | } | 
|  | 2861 |  | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 2862 | // Dig out the initializer, and use the declaration which it's attached to. | 
|  | 2863 | const Expr *Init = VD->getAnyInitializer(VD); | 
|  | 2864 | if (!Init || Init->isValueDependent()) { | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 2865 | // If we're checking a potential constant expression, the variable could be | 
|  | 2866 | // initialized later. | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 2867 | if (!Info.checkingPotentialConstantExpression()) | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2868 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 2869 | return false; | 
|  | 2870 | } | 
|  | 2871 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2872 | // If we're currently evaluating the initializer of this declaration, use that | 
|  | 2873 | // in-flight value. | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 2874 | if (Info.EvaluatingDecl.dyn_cast<const ValueDecl*>() == VD) { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 2875 | Result = Info.EvaluatingDeclValue; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 2876 | return true; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 2877 | } | 
|  | 2878 |  | 
| Richard Smith | cecf184 | 2011-11-01 21:06:14 +0000 | [diff] [blame] | 2879 | // Never evaluate the initializer of a weak variable. We can't be sure that | 
|  | 2880 | // this is the definition which will be used. | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 2881 | if (VD->isWeak()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2882 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Richard Smith | cecf184 | 2011-11-01 21:06:14 +0000 | [diff] [blame] | 2883 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 2884 | } | 
| Richard Smith | cecf184 | 2011-11-01 21:06:14 +0000 | [diff] [blame] | 2885 |  | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 2886 | // Check that we can fold the initializer. In C++, we will have already done | 
|  | 2887 | // this in the cases where it matters for conformance. | 
| Dmitri Gribenko | f857950 | 2013-01-12 19:30:44 +0000 | [diff] [blame] | 2888 | SmallVector<PartialDiagnosticAt, 8> Notes; | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 2889 | if (!VD->evaluateValue(Notes)) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 2890 | Info.FFDiag(E, diag::note_constexpr_var_init_non_constant, | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 2891 | Notes.size() + 1) << VD; | 
|  | 2892 | Info.Note(VD->getLocation(), diag::note_declared_at); | 
|  | 2893 | Info.addNotes(Notes); | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 2894 | return false; | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 2895 | } else if (!VD->checkInitIsICE()) { | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 2896 | Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant, | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 2897 | Notes.size() + 1) << VD; | 
|  | 2898 | Info.Note(VD->getLocation(), diag::note_declared_at); | 
|  | 2899 | Info.addNotes(Notes); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 2900 | } | 
| Richard Smith | 2790870 | 2011-10-24 17:54:18 +0000 | [diff] [blame] | 2901 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 2902 | Result = VD->getEvaluatedValue(); | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 2903 | return true; | 
| Richard Smith | 2790870 | 2011-10-24 17:54:18 +0000 | [diff] [blame] | 2904 | } | 
|  | 2905 |  | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 2906 | static bool IsConstNonVolatile(QualType T) { | 
| Richard Smith | 2790870 | 2011-10-24 17:54:18 +0000 | [diff] [blame] | 2907 | Qualifiers Quals = T.getQualifiers(); | 
|  | 2908 | return Quals.hasConst() && !Quals.hasVolatile(); | 
|  | 2909 | } | 
|  | 2910 |  | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 2911 | /// Get the base index of the given base class within an APValue representing | 
|  | 2912 | /// the given derived class. | 
|  | 2913 | static unsigned getBaseIndex(const CXXRecordDecl *Derived, | 
|  | 2914 | const CXXRecordDecl *Base) { | 
|  | 2915 | Base = Base->getCanonicalDecl(); | 
|  | 2916 | unsigned Index = 0; | 
|  | 2917 | for (CXXRecordDecl::base_class_const_iterator I = Derived->bases_begin(), | 
|  | 2918 | E = Derived->bases_end(); I != E; ++I, ++Index) { | 
|  | 2919 | if (I->getType()->getAsCXXRecordDecl()->getCanonicalDecl() == Base) | 
|  | 2920 | return Index; | 
|  | 2921 | } | 
|  | 2922 |  | 
|  | 2923 | llvm_unreachable("base class missing from derived class's bases list"); | 
|  | 2924 | } | 
|  | 2925 |  | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 2926 | /// Extract the value of a character from a string literal. | 
|  | 2927 | static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, | 
|  | 2928 | uint64_t Index) { | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 2929 | assert(!isa<SourceLocExpr>(Lit) && | 
|  | 2930 | "SourceLocExpr should have already been converted to a StringLiteral"); | 
|  | 2931 |  | 
| Akira Hatanaka | bc33264 | 2017-01-31 02:31:39 +0000 | [diff] [blame] | 2932 | // FIXME: Support MakeStringConstant | 
|  | 2933 | if (const auto *ObjCEnc = dyn_cast<ObjCEncodeExpr>(Lit)) { | 
|  | 2934 | std::string Str; | 
|  | 2935 | Info.Ctx.getObjCEncodingForType(ObjCEnc->getEncodedType(), Str); | 
|  | 2936 | assert(Index <= Str.size() && "Index too large"); | 
|  | 2937 | return APSInt::getUnsigned(Str.c_str()[Index]); | 
|  | 2938 | } | 
|  | 2939 |  | 
| Alexey Bataev | ec47478 | 2014-10-09 08:45:04 +0000 | [diff] [blame] | 2940 | if (auto PE = dyn_cast<PredefinedExpr>(Lit)) | 
|  | 2941 | Lit = PE->getFunctionName(); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 2942 | const StringLiteral *S = cast<StringLiteral>(Lit); | 
|  | 2943 | const ConstantArrayType *CAT = | 
|  | 2944 | Info.Ctx.getAsConstantArrayType(S->getType()); | 
|  | 2945 | assert(CAT && "string literal isn't an array"); | 
|  | 2946 | QualType CharType = CAT->getElementType(); | 
| Richard Smith | 9ec1e48 | 2012-04-15 02:50:59 +0000 | [diff] [blame] | 2947 | assert(CharType->isIntegerType() && "unexpected character type"); | 
| Richard Smith | 14a9413 | 2012-02-17 03:35:37 +0000 | [diff] [blame] | 2948 |  | 
|  | 2949 | APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(), | 
| Richard Smith | 9ec1e48 | 2012-04-15 02:50:59 +0000 | [diff] [blame] | 2950 | CharType->isUnsignedIntegerType()); | 
| Richard Smith | 14a9413 | 2012-02-17 03:35:37 +0000 | [diff] [blame] | 2951 | if (Index < S->getLength()) | 
|  | 2952 | Value = S->getCodeUnit(Index); | 
|  | 2953 | return Value; | 
|  | 2954 | } | 
|  | 2955 |  | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 2956 | // Expand a string literal into an array of characters. | 
| Eli Friedman | 3bf72d7 | 2019-02-08 21:18:46 +0000 | [diff] [blame] | 2957 | // | 
|  | 2958 | // FIXME: This is inefficient; we should probably introduce something similar | 
|  | 2959 | // to the LLVM ConstantDataArray to make this cheaper. | 
|  | 2960 | static void expandStringLiteral(EvalInfo &Info, const StringLiteral *S, | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 2961 | APValue &Result, | 
|  | 2962 | QualType AllocType = QualType()) { | 
|  | 2963 | const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType( | 
|  | 2964 | AllocType.isNull() ? S->getType() : AllocType); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 2965 | assert(CAT && "string literal isn't an array"); | 
|  | 2966 | QualType CharType = CAT->getElementType(); | 
|  | 2967 | assert(CharType->isIntegerType() && "unexpected character type"); | 
|  | 2968 |  | 
|  | 2969 | unsigned Elts = CAT->getSize().getZExtValue(); | 
|  | 2970 | Result = APValue(APValue::UninitArray(), | 
|  | 2971 | std::min(S->getLength(), Elts), Elts); | 
|  | 2972 | APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(), | 
|  | 2973 | CharType->isUnsignedIntegerType()); | 
|  | 2974 | if (Result.hasArrayFiller()) | 
|  | 2975 | Result.getArrayFiller() = APValue(Value); | 
|  | 2976 | for (unsigned I = 0, N = Result.getArrayInitializedElts(); I != N; ++I) { | 
|  | 2977 | Value = S->getCodeUnit(I); | 
|  | 2978 | Result.getArrayInitializedElt(I) = APValue(Value); | 
|  | 2979 | } | 
|  | 2980 | } | 
|  | 2981 |  | 
|  | 2982 | // Expand an array so that it has more than Index filled elements. | 
|  | 2983 | static void expandArray(APValue &Array, unsigned Index) { | 
|  | 2984 | unsigned Size = Array.getArraySize(); | 
|  | 2985 | assert(Index < Size); | 
|  | 2986 |  | 
|  | 2987 | // Always at least double the number of elements for which we store a value. | 
|  | 2988 | unsigned OldElts = Array.getArrayInitializedElts(); | 
|  | 2989 | unsigned NewElts = std::max(Index+1, OldElts * 2); | 
|  | 2990 | NewElts = std::min(Size, std::max(NewElts, 8u)); | 
|  | 2991 |  | 
|  | 2992 | // Copy the data across. | 
|  | 2993 | APValue NewValue(APValue::UninitArray(), NewElts, Size); | 
|  | 2994 | for (unsigned I = 0; I != OldElts; ++I) | 
|  | 2995 | NewValue.getArrayInitializedElt(I).swap(Array.getArrayInitializedElt(I)); | 
|  | 2996 | for (unsigned I = OldElts; I != NewElts; ++I) | 
|  | 2997 | NewValue.getArrayInitializedElt(I) = Array.getArrayFiller(); | 
|  | 2998 | if (NewValue.hasArrayFiller()) | 
|  | 2999 | NewValue.getArrayFiller() = Array.getArrayFiller(); | 
|  | 3000 | Array.swap(NewValue); | 
|  | 3001 | } | 
|  | 3002 |  | 
| Richard Smith | b01fe40 | 2014-09-16 01:24:02 +0000 | [diff] [blame] | 3003 | /// Determine whether a type would actually be read by an lvalue-to-rvalue | 
|  | 3004 | /// conversion. If it's of class type, we may assume that the copy operation | 
|  | 3005 | /// is trivial. Note that this is never true for a union type with fields | 
|  | 3006 | /// (because the copy always "reads" the active member) and always true for | 
|  | 3007 | /// a non-class type. | 
|  | 3008 | static bool isReadByLvalueToRvalueConversion(QualType T) { | 
|  | 3009 | CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); | 
|  | 3010 | if (!RD || (RD->isUnion() && !RD->field_empty())) | 
|  | 3011 | return true; | 
|  | 3012 | if (RD->isEmpty()) | 
|  | 3013 | return false; | 
|  | 3014 |  | 
|  | 3015 | for (auto *Field : RD->fields()) | 
|  | 3016 | if (isReadByLvalueToRvalueConversion(Field->getType())) | 
|  | 3017 | return true; | 
|  | 3018 |  | 
|  | 3019 | for (auto &BaseSpec : RD->bases()) | 
|  | 3020 | if (isReadByLvalueToRvalueConversion(BaseSpec.getType())) | 
|  | 3021 | return true; | 
|  | 3022 |  | 
|  | 3023 | return false; | 
|  | 3024 | } | 
|  | 3025 |  | 
|  | 3026 | /// Diagnose an attempt to read from any unreadable field within the specified | 
|  | 3027 | /// type, which might be a class type. | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3028 | static bool diagnoseMutableFields(EvalInfo &Info, const Expr *E, AccessKinds AK, | 
|  | 3029 | QualType T) { | 
| Richard Smith | b01fe40 | 2014-09-16 01:24:02 +0000 | [diff] [blame] | 3030 | CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); | 
|  | 3031 | if (!RD) | 
|  | 3032 | return false; | 
|  | 3033 |  | 
|  | 3034 | if (!RD->hasMutableFields()) | 
|  | 3035 | return false; | 
|  | 3036 |  | 
|  | 3037 | for (auto *Field : RD->fields()) { | 
|  | 3038 | // If we're actually going to read this field in some way, then it can't | 
|  | 3039 | // be mutable. If we're in a union, then assigning to a mutable field | 
|  | 3040 | // (even an empty one) can change the active member, so that's not OK. | 
|  | 3041 | // FIXME: Add core issue number for the union case. | 
|  | 3042 | if (Field->isMutable() && | 
|  | 3043 | (RD->isUnion() || isReadByLvalueToRvalueConversion(Field->getType()))) { | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3044 | Info.FFDiag(E, diag::note_constexpr_access_mutable, 1) << AK << Field; | 
| Richard Smith | b01fe40 | 2014-09-16 01:24:02 +0000 | [diff] [blame] | 3045 | Info.Note(Field->getLocation(), diag::note_declared_at); | 
|  | 3046 | return true; | 
|  | 3047 | } | 
|  | 3048 |  | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3049 | if (diagnoseMutableFields(Info, E, AK, Field->getType())) | 
| Richard Smith | b01fe40 | 2014-09-16 01:24:02 +0000 | [diff] [blame] | 3050 | return true; | 
|  | 3051 | } | 
|  | 3052 |  | 
|  | 3053 | for (auto &BaseSpec : RD->bases()) | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3054 | if (diagnoseMutableFields(Info, E, AK, BaseSpec.getType())) | 
| Richard Smith | b01fe40 | 2014-09-16 01:24:02 +0000 | [diff] [blame] | 3055 | return true; | 
|  | 3056 |  | 
|  | 3057 | // All mutable fields were empty, and thus not actually read. | 
|  | 3058 | return false; | 
|  | 3059 | } | 
|  | 3060 |  | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3061 | static bool lifetimeStartedInEvaluation(EvalInfo &Info, | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3062 | APValue::LValueBase Base, | 
|  | 3063 | bool MutableSubobject = false) { | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3064 | // A temporary we created. | 
|  | 3065 | if (Base.getCallIndex()) | 
|  | 3066 | return true; | 
|  | 3067 |  | 
|  | 3068 | auto *Evaluating = Info.EvaluatingDecl.dyn_cast<const ValueDecl*>(); | 
|  | 3069 | if (!Evaluating) | 
|  | 3070 | return false; | 
|  | 3071 |  | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3072 | auto *BaseD = Base.dyn_cast<const ValueDecl*>(); | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3073 |  | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3074 | switch (Info.IsEvaluatingDecl) { | 
|  | 3075 | case EvalInfo::EvaluatingDeclKind::None: | 
|  | 3076 | return false; | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3077 |  | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3078 | case EvalInfo::EvaluatingDeclKind::Ctor: | 
|  | 3079 | // The variable whose initializer we're evaluating. | 
|  | 3080 | if (BaseD) | 
|  | 3081 | return declaresSameEntity(Evaluating, BaseD); | 
|  | 3082 |  | 
|  | 3083 | // A temporary lifetime-extended by the variable whose initializer we're | 
|  | 3084 | // evaluating. | 
|  | 3085 | if (auto *BaseE = Base.dyn_cast<const Expr *>()) | 
|  | 3086 | if (auto *BaseMTE = dyn_cast<MaterializeTemporaryExpr>(BaseE)) | 
|  | 3087 | return declaresSameEntity(BaseMTE->getExtendingDecl(), Evaluating); | 
|  | 3088 | return false; | 
|  | 3089 |  | 
|  | 3090 | case EvalInfo::EvaluatingDeclKind::Dtor: | 
|  | 3091 | // C++2a [expr.const]p6: | 
|  | 3092 | //   [during constant destruction] the lifetime of a and its non-mutable | 
|  | 3093 | //   subobjects (but not its mutable subobjects) [are] considered to start | 
|  | 3094 | //   within e. | 
|  | 3095 | // | 
|  | 3096 | // FIXME: We can meaningfully extend this to cover non-const objects, but | 
|  | 3097 | // we will need special handling: we should be able to access only | 
|  | 3098 | // subobjects of such objects that are themselves declared const. | 
|  | 3099 | if (!BaseD || | 
|  | 3100 | !(BaseD->getType().isConstQualified() || | 
|  | 3101 | BaseD->getType()->isReferenceType()) || | 
|  | 3102 | MutableSubobject) | 
|  | 3103 | return false; | 
|  | 3104 | return declaresSameEntity(Evaluating, BaseD); | 
|  | 3105 | } | 
|  | 3106 |  | 
|  | 3107 | llvm_unreachable("unknown evaluating decl kind"); | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3108 | } | 
|  | 3109 |  | 
| Benjamin Kramer | 5b4296a | 2015-10-28 17:16:26 +0000 | [diff] [blame] | 3110 | namespace { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3111 | /// A handle to a complete object (an object that is not a subobject of | 
|  | 3112 | /// another object). | 
|  | 3113 | struct CompleteObject { | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3114 | /// The identity of the object. | 
|  | 3115 | APValue::LValueBase Base; | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3116 | /// The value of the complete object. | 
|  | 3117 | APValue *Value; | 
|  | 3118 | /// The type of the complete object. | 
|  | 3119 | QualType Type; | 
|  | 3120 |  | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 3121 | CompleteObject() : Value(nullptr) {} | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3122 | CompleteObject(APValue::LValueBase Base, APValue *Value, QualType Type) | 
|  | 3123 | : Base(Base), Value(Value), Type(Type) {} | 
|  | 3124 |  | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3125 | bool mayAccessMutableMembers(EvalInfo &Info, AccessKinds AK) const { | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3126 | // In C++14 onwards, it is permitted to read a mutable member whose | 
|  | 3127 | // lifetime began within the evaluation. | 
|  | 3128 | // FIXME: Should we also allow this in C++11? | 
|  | 3129 | if (!Info.getLangOpts().CPlusPlus14) | 
|  | 3130 | return false; | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3131 | return lifetimeStartedInEvaluation(Info, Base, /*MutableSubobject*/true); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3132 | } | 
|  | 3133 |  | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3134 | explicit operator bool() const { return !Type.isNull(); } | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3135 | }; | 
| Benjamin Kramer | 5b4296a | 2015-10-28 17:16:26 +0000 | [diff] [blame] | 3136 | } // end anonymous namespace | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3137 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3138 | static QualType getSubobjectType(QualType ObjType, QualType SubobjType, | 
|  | 3139 | bool IsMutable = false) { | 
|  | 3140 | // C++ [basic.type.qualifier]p1: | 
|  | 3141 | // - A const object is an object of type const T or a non-mutable subobject | 
|  | 3142 | //   of a const object. | 
|  | 3143 | if (ObjType.isConstQualified() && !IsMutable) | 
|  | 3144 | SubobjType.addConst(); | 
|  | 3145 | // - A volatile object is an object of type const T or a subobject of a | 
|  | 3146 | //   volatile object. | 
|  | 3147 | if (ObjType.isVolatileQualified()) | 
|  | 3148 | SubobjType.addVolatile(); | 
|  | 3149 | return SubobjType; | 
|  | 3150 | } | 
|  | 3151 |  | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3152 | /// Find the designated sub-object of an rvalue. | 
|  | 3153 | template<typename SubobjectHandler> | 
|  | 3154 | typename SubobjectHandler::result_type | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3155 | findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3156 | const SubobjectDesignator &Sub, SubobjectHandler &handler) { | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 3157 | if (Sub.Invalid) | 
|  | 3158 | // A diagnostic will have already been produced. | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3159 | return handler.failed(); | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 3160 | if (Sub.isOnePastTheEnd() || Sub.isMostDerivedAnUnsizedArray()) { | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3161 | if (Info.getLangOpts().CPlusPlus11) | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 3162 | Info.FFDiag(E, Sub.isOnePastTheEnd() | 
|  | 3163 | ? diag::note_constexpr_access_past_end | 
|  | 3164 | : diag::note_constexpr_access_unsized_array) | 
|  | 3165 | << handler.AccessKind; | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3166 | else | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3167 | Info.FFDiag(E); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3168 | return handler.failed(); | 
| Richard Smith | f2b681b | 2011-12-21 05:04:46 +0000 | [diff] [blame] | 3169 | } | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 3170 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3171 | APValue *O = Obj.Value; | 
|  | 3172 | QualType ObjType = Obj.Type; | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 3173 | const FieldDecl *LastField = nullptr; | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3174 | const FieldDecl *VolatileField = nullptr; | 
| Richard Smith | 49ca8aa | 2013-08-06 07:09:20 +0000 | [diff] [blame] | 3175 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 3176 | // Walk the designator's path to find the subobject. | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 3177 | for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 3178 | // Reading an indeterminate value is undefined, but assigning over one is OK. | 
| Richard Smith | e381f33 | 2019-10-10 22:31:17 +0000 | [diff] [blame] | 3179 | if ((O->isAbsent() && !(handler.AccessKind == AK_Construct && I == N)) || | 
| Richard Smith | b542602 | 2019-10-03 00:39:35 +0000 | [diff] [blame] | 3180 | (O->isIndeterminate() && handler.AccessKind != AK_Construct && | 
|  | 3181 | handler.AccessKind != AK_Assign && | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3182 | handler.AccessKind != AK_ReadObjectRepresentation)) { | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 3183 | if (!Info.checkingPotentialConstantExpression()) | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3184 | Info.FFDiag(E, diag::note_constexpr_access_uninit) | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 3185 | << handler.AccessKind << O->isIndeterminate(); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 3186 | return handler.failed(); | 
|  | 3187 | } | 
|  | 3188 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 3189 | // C++ [class.ctor]p5, C++ [class.dtor]p5: | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3190 | //    const and volatile semantics are not applied on an object under | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 3191 | //    {con,de}struction. | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3192 | if ((ObjType.isConstQualified() || ObjType.isVolatileQualified()) && | 
|  | 3193 | ObjType->isRecordType() && | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 3194 | Info.isEvaluatingCtorDtor( | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3195 | Obj.Base, llvm::makeArrayRef(Sub.Entries.begin(), | 
|  | 3196 | Sub.Entries.begin() + I)) != | 
|  | 3197 | ConstructionPhase::None) { | 
|  | 3198 | ObjType = Info.Ctx.getCanonicalType(ObjType); | 
|  | 3199 | ObjType.removeLocalConst(); | 
|  | 3200 | ObjType.removeLocalVolatile(); | 
|  | 3201 | } | 
|  | 3202 |  | 
|  | 3203 | // If this is our last pass, check that the final object type is OK. | 
|  | 3204 | if (I == N || (I == N - 1 && ObjType->isAnyComplexType())) { | 
|  | 3205 | // Accesses to volatile objects are prohibited. | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 3206 | if (ObjType.isVolatileQualified() && isFormalAccess(handler.AccessKind)) { | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3207 | if (Info.getLangOpts().CPlusPlus) { | 
|  | 3208 | int DiagKind; | 
|  | 3209 | SourceLocation Loc; | 
|  | 3210 | const NamedDecl *Decl = nullptr; | 
|  | 3211 | if (VolatileField) { | 
|  | 3212 | DiagKind = 2; | 
|  | 3213 | Loc = VolatileField->getLocation(); | 
|  | 3214 | Decl = VolatileField; | 
|  | 3215 | } else if (auto *VD = Obj.Base.dyn_cast<const ValueDecl*>()) { | 
|  | 3216 | DiagKind = 1; | 
|  | 3217 | Loc = VD->getLocation(); | 
|  | 3218 | Decl = VD; | 
|  | 3219 | } else { | 
|  | 3220 | DiagKind = 0; | 
|  | 3221 | if (auto *E = Obj.Base.dyn_cast<const Expr *>()) | 
|  | 3222 | Loc = E->getExprLoc(); | 
|  | 3223 | } | 
|  | 3224 | Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) | 
|  | 3225 | << handler.AccessKind << DiagKind << Decl; | 
|  | 3226 | Info.Note(Loc, diag::note_constexpr_volatile_here) << DiagKind; | 
|  | 3227 | } else { | 
|  | 3228 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
|  | 3229 | } | 
|  | 3230 | return handler.failed(); | 
|  | 3231 | } | 
|  | 3232 |  | 
| Richard Smith | b01fe40 | 2014-09-16 01:24:02 +0000 | [diff] [blame] | 3233 | // If we are reading an object of class type, there may still be more | 
|  | 3234 | // things we need to check: if there are any mutable subobjects, we | 
|  | 3235 | // cannot perform this read. (This only happens when performing a trivial | 
|  | 3236 | // copy or assignment.) | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3237 | if (ObjType->isRecordType() && | 
|  | 3238 | !Obj.mayAccessMutableMembers(Info, handler.AccessKind) && | 
|  | 3239 | diagnoseMutableFields(Info, E, handler.AccessKind, ObjType)) | 
| Richard Smith | b01fe40 | 2014-09-16 01:24:02 +0000 | [diff] [blame] | 3240 | return handler.failed(); | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3241 | } | 
| Richard Smith | b01fe40 | 2014-09-16 01:24:02 +0000 | [diff] [blame] | 3242 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3243 | if (I == N) { | 
| Richard Smith | 49ca8aa | 2013-08-06 07:09:20 +0000 | [diff] [blame] | 3244 | if (!handler.found(*O, ObjType)) | 
|  | 3245 | return false; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 3246 |  | 
| Richard Smith | 49ca8aa | 2013-08-06 07:09:20 +0000 | [diff] [blame] | 3247 | // If we modified a bit-field, truncate it to the right width. | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3248 | if (isModification(handler.AccessKind) && | 
| Richard Smith | 49ca8aa | 2013-08-06 07:09:20 +0000 | [diff] [blame] | 3249 | LastField && LastField->isBitField() && | 
|  | 3250 | !truncateBitfieldValue(Info, E, *O, LastField)) | 
|  | 3251 | return false; | 
|  | 3252 |  | 
|  | 3253 | return true; | 
|  | 3254 | } | 
|  | 3255 |  | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 3256 | LastField = nullptr; | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 3257 | if (ObjType->isArrayType()) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 3258 | // Next subobject is an array element. | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 3259 | const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 3260 | assert(CAT && "vla in literal type?"); | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 3261 | uint64_t Index = Sub.Entries[I].getAsArrayIndex(); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 3262 | if (CAT->getSize().ule(Index)) { | 
| Richard Smith | f2b681b | 2011-12-21 05:04:46 +0000 | [diff] [blame] | 3263 | // Note, it should not be possible to form a pointer with a valid | 
|  | 3264 | // designator which points more than one past the end of the array. | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3265 | if (Info.getLangOpts().CPlusPlus11) | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3266 | Info.FFDiag(E, diag::note_constexpr_access_past_end) | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3267 | << handler.AccessKind; | 
|  | 3268 | else | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3269 | Info.FFDiag(E); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3270 | return handler.failed(); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 3271 | } | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3272 |  | 
|  | 3273 | ObjType = CAT->getElementType(); | 
|  | 3274 |  | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3275 | if (O->getArrayInitializedElts() > Index) | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 3276 | O = &O->getArrayInitializedElt(Index); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3277 | else if (!isRead(handler.AccessKind)) { | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3278 | expandArray(*O, Index); | 
|  | 3279 | O = &O->getArrayInitializedElt(Index); | 
|  | 3280 | } else | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 3281 | O = &O->getArrayFiller(); | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 3282 | } else if (ObjType->isAnyComplexType()) { | 
|  | 3283 | // Next subobject is a complex number. | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 3284 | uint64_t Index = Sub.Entries[I].getAsArrayIndex(); | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 3285 | if (Index > 1) { | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3286 | if (Info.getLangOpts().CPlusPlus11) | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3287 | Info.FFDiag(E, diag::note_constexpr_access_past_end) | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3288 | << handler.AccessKind; | 
|  | 3289 | else | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3290 | Info.FFDiag(E); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3291 | return handler.failed(); | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 3292 | } | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3293 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3294 | ObjType = getSubobjectType( | 
|  | 3295 | ObjType, ObjType->castAs<ComplexType>()->getElementType()); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3296 |  | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 3297 | assert(I == N - 1 && "extracting subobject of scalar?"); | 
|  | 3298 | if (O->isComplexInt()) { | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3299 | return handler.found(Index ? O->getComplexIntImag() | 
|  | 3300 | : O->getComplexIntReal(), ObjType); | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 3301 | } else { | 
|  | 3302 | assert(O->isComplexFloat()); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3303 | return handler.found(Index ? O->getComplexFloatImag() | 
|  | 3304 | : O->getComplexFloatReal(), ObjType); | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 3305 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 3306 | } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3307 | if (Field->isMutable() && | 
|  | 3308 | !Obj.mayAccessMutableMembers(Info, handler.AccessKind)) { | 
|  | 3309 | Info.FFDiag(E, diag::note_constexpr_access_mutable, 1) | 
|  | 3310 | << handler.AccessKind << Field; | 
| Richard Smith | 5a294e6 | 2012-02-09 03:29:58 +0000 | [diff] [blame] | 3311 | Info.Note(Field->getLocation(), diag::note_declared_at); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3312 | return handler.failed(); | 
| Richard Smith | 5a294e6 | 2012-02-09 03:29:58 +0000 | [diff] [blame] | 3313 | } | 
|  | 3314 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 3315 | // Next subobject is a class, struct or union field. | 
|  | 3316 | RecordDecl *RD = ObjType->castAs<RecordType>()->getDecl(); | 
|  | 3317 | if (RD->isUnion()) { | 
|  | 3318 | const FieldDecl *UnionField = O->getUnionField(); | 
|  | 3319 | if (!UnionField || | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 3320 | UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) { | 
| Richard Smith | b542602 | 2019-10-03 00:39:35 +0000 | [diff] [blame] | 3321 | if (I == N - 1 && handler.AccessKind == AK_Construct) { | 
|  | 3322 | // Placement new onto an inactive union member makes it active. | 
|  | 3323 | O->setUnion(Field, APValue()); | 
|  | 3324 | } else { | 
|  | 3325 | // FIXME: If O->getUnionValue() is absent, report that there's no | 
|  | 3326 | // active union member rather than reporting the prior active union | 
|  | 3327 | // member. We'll need to fix nullptr_t to not use APValue() as its | 
|  | 3328 | // representation first. | 
|  | 3329 | Info.FFDiag(E, diag::note_constexpr_access_inactive_union_member) | 
|  | 3330 | << handler.AccessKind << Field << !UnionField << UnionField; | 
|  | 3331 | return handler.failed(); | 
|  | 3332 | } | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 3333 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 3334 | O = &O->getUnionValue(); | 
|  | 3335 | } else | 
|  | 3336 | O = &O->getStructField(Field->getFieldIndex()); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3337 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3338 | ObjType = getSubobjectType(ObjType, Field->getType(), Field->isMutable()); | 
| Richard Smith | 49ca8aa | 2013-08-06 07:09:20 +0000 | [diff] [blame] | 3339 | LastField = Field; | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3340 | if (Field->getType().isVolatileQualified()) | 
|  | 3341 | VolatileField = Field; | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 3342 | } else { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 3343 | // Next subobject is a base class. | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 3344 | const CXXRecordDecl *Derived = ObjType->getAsCXXRecordDecl(); | 
|  | 3345 | const CXXRecordDecl *Base = getAsBaseClass(Sub.Entries[I]); | 
|  | 3346 | O = &O->getStructBase(getBaseIndex(Derived, Base)); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3347 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 3348 | ObjType = getSubobjectType(ObjType, Info.Ctx.getRecordType(Base)); | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 3349 | } | 
|  | 3350 | } | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3351 | } | 
|  | 3352 |  | 
| Benjamin Kramer | 62498ab | 2013-04-26 22:01:47 +0000 | [diff] [blame] | 3353 | namespace { | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3354 | struct ExtractSubobjectHandler { | 
|  | 3355 | EvalInfo &Info; | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3356 | const Expr *E; | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3357 | APValue &Result; | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3358 | const AccessKinds AccessKind; | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3359 |  | 
|  | 3360 | typedef bool result_type; | 
|  | 3361 | bool failed() { return false; } | 
|  | 3362 | bool found(APValue &Subobj, QualType SubobjType) { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3363 | Result = Subobj; | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3364 | if (AccessKind == AK_ReadObjectRepresentation) | 
|  | 3365 | return true; | 
|  | 3366 | return CheckFullyInitialized(Info, E->getExprLoc(), SubobjType, Result); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3367 | } | 
|  | 3368 | bool found(APSInt &Value, QualType SubobjType) { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3369 | Result = APValue(Value); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3370 | return true; | 
|  | 3371 | } | 
|  | 3372 | bool found(APFloat &Value, QualType SubobjType) { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3373 | Result = APValue(Value); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3374 | return true; | 
|  | 3375 | } | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3376 | }; | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3377 | } // end anonymous namespace | 
|  | 3378 |  | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3379 | /// Extract the designated sub-object of an rvalue. | 
|  | 3380 | static bool extractSubobject(EvalInfo &Info, const Expr *E, | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3381 | const CompleteObject &Obj, | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3382 | const SubobjectDesignator &Sub, APValue &Result, | 
|  | 3383 | AccessKinds AK = AK_Read) { | 
|  | 3384 | assert(AK == AK_Read || AK == AK_ReadObjectRepresentation); | 
|  | 3385 | ExtractSubobjectHandler Handler = {Info, E, Result, AK}; | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3386 | return findSubobject(Info, E, Obj, Sub, Handler); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3387 | } | 
|  | 3388 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3389 | namespace { | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3390 | struct ModifySubobjectHandler { | 
|  | 3391 | EvalInfo &Info; | 
|  | 3392 | APValue &NewVal; | 
|  | 3393 | const Expr *E; | 
|  | 3394 |  | 
|  | 3395 | typedef bool result_type; | 
|  | 3396 | static const AccessKinds AccessKind = AK_Assign; | 
|  | 3397 |  | 
|  | 3398 | bool checkConst(QualType QT) { | 
|  | 3399 | // Assigning to a const object has undefined behavior. | 
|  | 3400 | if (QT.isConstQualified()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3401 | Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3402 | return false; | 
|  | 3403 | } | 
|  | 3404 | return true; | 
|  | 3405 | } | 
|  | 3406 |  | 
|  | 3407 | bool failed() { return false; } | 
|  | 3408 | bool found(APValue &Subobj, QualType SubobjType) { | 
|  | 3409 | if (!checkConst(SubobjType)) | 
|  | 3410 | return false; | 
|  | 3411 | // We've been given ownership of NewVal, so just swap it in. | 
|  | 3412 | Subobj.swap(NewVal); | 
|  | 3413 | return true; | 
|  | 3414 | } | 
|  | 3415 | bool found(APSInt &Value, QualType SubobjType) { | 
|  | 3416 | if (!checkConst(SubobjType)) | 
|  | 3417 | return false; | 
|  | 3418 | if (!NewVal.isInt()) { | 
|  | 3419 | // Maybe trying to write a cast pointer value into a complex? | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3420 | Info.FFDiag(E); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3421 | return false; | 
|  | 3422 | } | 
|  | 3423 | Value = NewVal.getInt(); | 
|  | 3424 | return true; | 
|  | 3425 | } | 
|  | 3426 | bool found(APFloat &Value, QualType SubobjType) { | 
|  | 3427 | if (!checkConst(SubobjType)) | 
|  | 3428 | return false; | 
|  | 3429 | Value = NewVal.getFloat(); | 
|  | 3430 | return true; | 
|  | 3431 | } | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3432 | }; | 
| Benjamin Kramer | 62498ab | 2013-04-26 22:01:47 +0000 | [diff] [blame] | 3433 | } // end anonymous namespace | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3434 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3435 | const AccessKinds ModifySubobjectHandler::AccessKind; | 
|  | 3436 |  | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3437 | /// Update the designated sub-object of an rvalue to the given value. | 
|  | 3438 | static bool modifySubobject(EvalInfo &Info, const Expr *E, | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3439 | const CompleteObject &Obj, | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3440 | const SubobjectDesignator &Sub, | 
|  | 3441 | APValue &NewVal) { | 
|  | 3442 | ModifySubobjectHandler Handler = { Info, NewVal, E }; | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3443 | return findSubobject(Info, E, Obj, Sub, Handler); | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 3444 | } | 
|  | 3445 |  | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 3446 | /// Find the position where two subobject designators diverge, or equivalently | 
|  | 3447 | /// the length of the common initial subsequence. | 
|  | 3448 | static unsigned FindDesignatorMismatch(QualType ObjType, | 
|  | 3449 | const SubobjectDesignator &A, | 
|  | 3450 | const SubobjectDesignator &B, | 
|  | 3451 | bool &WasArrayIndex) { | 
|  | 3452 | unsigned I = 0, N = std::min(A.Entries.size(), B.Entries.size()); | 
|  | 3453 | for (/**/; I != N; ++I) { | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 3454 | if (!ObjType.isNull() && | 
|  | 3455 | (ObjType->isArrayType() || ObjType->isAnyComplexType())) { | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 3456 | // Next subobject is an array element. | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 3457 | if (A.Entries[I].getAsArrayIndex() != B.Entries[I].getAsArrayIndex()) { | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 3458 | WasArrayIndex = true; | 
|  | 3459 | return I; | 
|  | 3460 | } | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 3461 | if (ObjType->isAnyComplexType()) | 
|  | 3462 | ObjType = ObjType->castAs<ComplexType>()->getElementType(); | 
|  | 3463 | else | 
|  | 3464 | ObjType = ObjType->castAsArrayTypeUnsafe()->getElementType(); | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 3465 | } else { | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 3466 | if (A.Entries[I].getAsBaseOrMember() != | 
|  | 3467 | B.Entries[I].getAsBaseOrMember()) { | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 3468 | WasArrayIndex = false; | 
|  | 3469 | return I; | 
|  | 3470 | } | 
|  | 3471 | if (const FieldDecl *FD = getAsField(A.Entries[I])) | 
|  | 3472 | // Next subobject is a field. | 
|  | 3473 | ObjType = FD->getType(); | 
|  | 3474 | else | 
|  | 3475 | // Next subobject is a base class. | 
|  | 3476 | ObjType = QualType(); | 
|  | 3477 | } | 
|  | 3478 | } | 
|  | 3479 | WasArrayIndex = false; | 
|  | 3480 | return I; | 
|  | 3481 | } | 
|  | 3482 |  | 
|  | 3483 | /// Determine whether the given subobject designators refer to elements of the | 
|  | 3484 | /// same array object. | 
|  | 3485 | static bool AreElementsOfSameArray(QualType ObjType, | 
|  | 3486 | const SubobjectDesignator &A, | 
|  | 3487 | const SubobjectDesignator &B) { | 
|  | 3488 | if (A.Entries.size() != B.Entries.size()) | 
|  | 3489 | return false; | 
|  | 3490 |  | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 3491 | bool IsArray = A.MostDerivedIsArrayElement; | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 3492 | if (IsArray && A.MostDerivedPathLength != A.Entries.size()) | 
|  | 3493 | // A is a subobject of the array element. | 
|  | 3494 | return false; | 
|  | 3495 |  | 
|  | 3496 | // If A (and B) designates an array element, the last entry will be the array | 
|  | 3497 | // index. That doesn't have to match. Otherwise, we're in the 'implicit array | 
|  | 3498 | // of length 1' case, and the entire path must match. | 
|  | 3499 | bool WasArrayIndex; | 
|  | 3500 | unsigned CommonLength = FindDesignatorMismatch(ObjType, A, B, WasArrayIndex); | 
|  | 3501 | return CommonLength >= A.Entries.size() - IsArray; | 
|  | 3502 | } | 
|  | 3503 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3504 | /// Find the complete object to which an LValue refers. | 
| Benjamin Kramer | 8407df7 | 2015-03-09 16:47:52 +0000 | [diff] [blame] | 3505 | static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, | 
|  | 3506 | AccessKinds AK, const LValue &LVal, | 
|  | 3507 | QualType LValType) { | 
| Richard Smith | 51ce844 | 2019-05-17 08:01:34 +0000 | [diff] [blame] | 3508 | if (LVal.InvalidBase) { | 
|  | 3509 | Info.FFDiag(E); | 
|  | 3510 | return CompleteObject(); | 
|  | 3511 | } | 
|  | 3512 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3513 | if (!LVal.Base) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3514 | Info.FFDiag(E, diag::note_constexpr_access_null) << AK; | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3515 | return CompleteObject(); | 
|  | 3516 | } | 
|  | 3517 |  | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 3518 | CallStackFrame *Frame = nullptr; | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 3519 | unsigned Depth = 0; | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 3520 | if (LVal.getLValueCallIndex()) { | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 3521 | std::tie(Frame, Depth) = | 
|  | 3522 | Info.getCallFrameAndDepth(LVal.getLValueCallIndex()); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3523 | if (!Frame) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3524 | Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1) | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3525 | << AK << LVal.Base.is<const ValueDecl*>(); | 
|  | 3526 | NoteLValueLocation(Info, LVal.Base); | 
|  | 3527 | return CompleteObject(); | 
|  | 3528 | } | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3529 | } | 
|  | 3530 |  | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 3531 | bool IsAccess = isAnyAccess(AK); | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 3532 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3533 | // C++11 DR1311: An lvalue-to-rvalue conversion on a volatile-qualified type | 
|  | 3534 | // is not a constant expression (even if the object is non-volatile). We also | 
|  | 3535 | // apply this rule to C++98, in order to conform to the expected 'volatile' | 
|  | 3536 | // semantics. | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 3537 | if (isFormalAccess(AK) && LValType.isVolatileQualified()) { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3538 | if (Info.getLangOpts().CPlusPlus) | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3539 | Info.FFDiag(E, diag::note_constexpr_access_volatile_type) | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3540 | << AK << LValType; | 
|  | 3541 | else | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3542 | Info.FFDiag(E); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3543 | return CompleteObject(); | 
|  | 3544 | } | 
|  | 3545 |  | 
|  | 3546 | // Compute value storage location and type of base object. | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 3547 | APValue *BaseVal = nullptr; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 3548 | QualType BaseType = getType(LVal.Base); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3549 |  | 
|  | 3550 | if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) { | 
|  | 3551 | // In C++98, const, non-volatile integers initialized with ICEs are ICEs. | 
|  | 3552 | // In C++11, constexpr, non-volatile variables initialized with constant | 
|  | 3553 | // expressions are constant expressions too. Inside constexpr functions, | 
|  | 3554 | // parameters are constant expressions even if they're non-const. | 
|  | 3555 | // In C++1y, objects local to a constant expression (those with a Frame) are | 
|  | 3556 | // both readable and writable inside constant expressions. | 
|  | 3557 | // In C, such things can also be folded, although they are not ICEs. | 
|  | 3558 | const VarDecl *VD = dyn_cast<VarDecl>(D); | 
|  | 3559 | if (VD) { | 
|  | 3560 | if (const VarDecl *VDef = VD->getDefinition(Info.Ctx)) | 
|  | 3561 | VD = VDef; | 
|  | 3562 | } | 
|  | 3563 | if (!VD || VD->isInvalidDecl()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3564 | Info.FFDiag(E); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3565 | return CompleteObject(); | 
|  | 3566 | } | 
|  | 3567 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3568 | // Unless we're looking at a local variable or argument in a constexpr call, | 
|  | 3569 | // the variable we're reading must be const. | 
|  | 3570 | if (!Frame) { | 
| Aaron Ballman | dd69ef3 | 2014-08-19 15:55:55 +0000 | [diff] [blame] | 3571 | if (Info.getLangOpts().CPlusPlus14 && | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3572 | lifetimeStartedInEvaluation(Info, LVal.Base)) { | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 3573 | // OK, we can read and modify an object if we're in the process of | 
|  | 3574 | // evaluating its initializer, because its lifetime began in this | 
|  | 3575 | // evaluation. | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3576 | } else if (isModification(AK)) { | 
|  | 3577 | // All the remaining cases do not permit modification of the object. | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3578 | Info.FFDiag(E, diag::note_constexpr_modify_global); | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 3579 | return CompleteObject(); | 
| George Burgess IV | b531698 | 2016-12-27 05:33:20 +0000 | [diff] [blame] | 3580 | } else if (VD->isConstexpr()) { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3581 | // OK, we can read this variable. | 
|  | 3582 | } else if (BaseType->isIntegralOrEnumerationType()) { | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3583 | // In OpenCL if a variable is in constant address space it is a const | 
|  | 3584 | // value. | 
| Xiuli Pan | 244e3f6 | 2016-06-07 04:34:00 +0000 | [diff] [blame] | 3585 | if (!(BaseType.isConstQualified() || | 
|  | 3586 | (Info.getLangOpts().OpenCL && | 
|  | 3587 | BaseType.getAddressSpace() == LangAS::opencl_constant))) { | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 3588 | if (!IsAccess) | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3589 | return CompleteObject(LVal.getLValueBase(), nullptr, BaseType); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3590 | if (Info.getLangOpts().CPlusPlus) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3591 | Info.FFDiag(E, diag::note_constexpr_ltor_non_const_int, 1) << VD; | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3592 | Info.Note(VD->getLocation(), diag::note_declared_at); | 
|  | 3593 | } else { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3594 | Info.FFDiag(E); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3595 | } | 
|  | 3596 | return CompleteObject(); | 
|  | 3597 | } | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 3598 | } else if (!IsAccess) { | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3599 | return CompleteObject(LVal.getLValueBase(), nullptr, BaseType); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3600 | } else if (BaseType->isFloatingType() && BaseType.isConstQualified()) { | 
|  | 3601 | // We support folding of const floating-point types, in order to make | 
|  | 3602 | // static const data members of such types (supported as an extension) | 
|  | 3603 | // more useful. | 
|  | 3604 | if (Info.getLangOpts().CPlusPlus11) { | 
|  | 3605 | Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD; | 
|  | 3606 | Info.Note(VD->getLocation(), diag::note_declared_at); | 
|  | 3607 | } else { | 
|  | 3608 | Info.CCEDiag(E); | 
|  | 3609 | } | 
| George Burgess IV | b531698 | 2016-12-27 05:33:20 +0000 | [diff] [blame] | 3610 | } else if (BaseType.isConstQualified() && VD->hasDefinition(Info.Ctx)) { | 
|  | 3611 | Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr) << VD; | 
|  | 3612 | // Keep evaluating to see what we can do. | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3613 | } else { | 
|  | 3614 | // FIXME: Allow folding of values of any literal type in all languages. | 
| Richard Smith | c0d04a2 | 2016-05-25 22:06:25 +0000 | [diff] [blame] | 3615 | if (Info.checkingPotentialConstantExpression() && | 
|  | 3616 | VD->getType().isConstQualified() && !VD->hasDefinition(Info.Ctx)) { | 
|  | 3617 | // The definition of this variable could be constexpr. We can't | 
|  | 3618 | // access it right now, but may be able to in future. | 
|  | 3619 | } else if (Info.getLangOpts().CPlusPlus11) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3620 | Info.FFDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD; | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3621 | Info.Note(VD->getLocation(), diag::note_declared_at); | 
|  | 3622 | } else { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3623 | Info.FFDiag(E); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3624 | } | 
|  | 3625 | return CompleteObject(); | 
|  | 3626 | } | 
|  | 3627 | } | 
|  | 3628 |  | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 3629 | if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal, &LVal)) | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3630 | return CompleteObject(); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 3631 | } else if (DynamicAllocLValue DA = LVal.Base.dyn_cast<DynamicAllocLValue>()) { | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 3632 | Optional<DynAlloc*> Alloc = Info.lookupDynamicAlloc(DA); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 3633 | if (!Alloc) { | 
|  | 3634 | Info.FFDiag(E, diag::note_constexpr_access_deleted_object) << AK; | 
|  | 3635 | return CompleteObject(); | 
|  | 3636 | } | 
|  | 3637 | return CompleteObject(LVal.Base, &(*Alloc)->Value, | 
|  | 3638 | LVal.Base.getDynamicAllocType()); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3639 | } else { | 
|  | 3640 | const Expr *Base = LVal.Base.dyn_cast<const Expr*>(); | 
|  | 3641 |  | 
|  | 3642 | if (!Frame) { | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 3643 | if (const MaterializeTemporaryExpr *MTE = | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 3644 | dyn_cast_or_null<MaterializeTemporaryExpr>(Base)) { | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 3645 | assert(MTE->getStorageDuration() == SD_Static && | 
|  | 3646 | "should have a frame for a non-global materialized temporary"); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3647 |  | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 3648 | // Per C++1y [expr.const]p2: | 
|  | 3649 | //  an lvalue-to-rvalue conversion [is not allowed unless it applies to] | 
|  | 3650 | //   - a [...] glvalue of integral or enumeration type that refers to | 
|  | 3651 | //     a non-volatile const object [...] | 
|  | 3652 | //   [...] | 
|  | 3653 | //   - a [...] glvalue of literal type that refers to a non-volatile | 
|  | 3654 | //     object whose lifetime began within the evaluation of e. | 
|  | 3655 | // | 
|  | 3656 | // C++11 misses the 'began within the evaluation of e' check and | 
|  | 3657 | // instead allows all temporaries, including things like: | 
|  | 3658 | //   int &&r = 1; | 
|  | 3659 | //   int x = ++r; | 
|  | 3660 | //   constexpr int k = r; | 
| Richard Smith | 9defb7d | 2018-02-21 03:38:30 +0000 | [diff] [blame] | 3661 | // Therefore we use the C++14 rules in C++11 too. | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3662 | // | 
|  | 3663 | // Note that temporaries whose lifetimes began while evaluating a | 
|  | 3664 | // variable's constructor are not usable while evaluating the | 
|  | 3665 | // corresponding destructor, not even if they're of const-qualified | 
|  | 3666 | // types. | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 3667 | if (!(BaseType.isConstQualified() && | 
|  | 3668 | BaseType->isIntegralOrEnumerationType()) && | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 3669 | !lifetimeStartedInEvaluation(Info, LVal.Base)) { | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 3670 | if (!IsAccess) | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3671 | return CompleteObject(LVal.getLValueBase(), nullptr, BaseType); | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3672 | Info.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK; | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 3673 | Info.Note(MTE->getExprLoc(), diag::note_constexpr_temporary_here); | 
|  | 3674 | return CompleteObject(); | 
|  | 3675 | } | 
|  | 3676 |  | 
| Tyker | b0561b3 | 2019-11-17 11:41:55 +0100 | [diff] [blame] | 3677 | BaseVal = MTE->getOrCreateValue(false); | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 3678 | assert(BaseVal && "got reference to unevaluated temporary"); | 
|  | 3679 | } else { | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 3680 | if (!IsAccess) | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3681 | return CompleteObject(LVal.getLValueBase(), nullptr, BaseType); | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 3682 | APValue Val; | 
|  | 3683 | LVal.moveInto(Val); | 
|  | 3684 | Info.FFDiag(E, diag::note_constexpr_access_unreadable_object) | 
|  | 3685 | << AK | 
|  | 3686 | << Val.getAsString(Info.Ctx, | 
|  | 3687 | Info.Ctx.getLValueReferenceType(LValType)); | 
|  | 3688 | NoteLValueLocation(Info, LVal.Base); | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 3689 | return CompleteObject(); | 
|  | 3690 | } | 
|  | 3691 | } else { | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 3692 | BaseVal = Frame->getTemporary(Base, LVal.Base.getVersion()); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 3693 | assert(BaseVal && "missing value for temporary"); | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 3694 | } | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 3695 | } | 
|  | 3696 |  | 
| Richard Smith | 9defb7d | 2018-02-21 03:38:30 +0000 | [diff] [blame] | 3697 | // In C++14, we can't safely access any mutable state when we might be | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 3698 | // evaluating after an unmodeled side effect. | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 3699 | // | 
|  | 3700 | // FIXME: Not all local state is mutable. Allow local constant subobjects | 
|  | 3701 | // to be read here (but take care with 'mutable' fields). | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 3702 | if ((Frame && Info.getLangOpts().CPlusPlus14 && | 
|  | 3703 | Info.EvalStatus.HasSideEffects) || | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3704 | (isModification(AK) && Depth < Info.SpeculativeEvaluationDepth)) | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3705 | return CompleteObject(); | 
|  | 3706 |  | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3707 | return CompleteObject(LVal.getLValueBase(), BaseVal, BaseType); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3708 | } | 
|  | 3709 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 3710 | /// Perform an lvalue-to-rvalue conversion on the given glvalue. This | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 3711 | /// can also be used for 'lvalue-to-lvalue' conversions for looking up the | 
|  | 3712 | /// glvalue referred to by an entity of reference type. | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 3713 | /// | 
|  | 3714 | /// \param Info - Information about the ongoing evaluation. | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 3715 | /// \param Conv - The expression for which we are performing the conversion. | 
|  | 3716 | ///               Used for diagnostics. | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3717 | /// \param Type - The type of the glvalue (before stripping cv-qualifiers in the | 
|  | 3718 | ///               case of a non-class type). | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 3719 | /// \param LVal - The glvalue on which we are attempting to perform this action. | 
|  | 3720 | /// \param RVal - The produced value will be placed here. | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3721 | /// \param WantObjectRepresentation - If true, we're looking for the object | 
|  | 3722 | ///               representation rather than the value, and in particular, | 
|  | 3723 | ///               there is no requirement that the result be fully initialized. | 
|  | 3724 | static bool | 
|  | 3725 | handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, QualType Type, | 
|  | 3726 | const LValue &LVal, APValue &RVal, | 
|  | 3727 | bool WantObjectRepresentation = false) { | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 3728 | if (LVal.Designator.Invalid) | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 3729 | return false; | 
|  | 3730 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3731 | // Check for special cases where there is no existing APValue to look at. | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 3732 | const Expr *Base = LVal.Base.dyn_cast<const Expr*>(); | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 3733 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3734 | AccessKinds AK = | 
|  | 3735 | WantObjectRepresentation ? AK_ReadObjectRepresentation : AK_Read; | 
|  | 3736 |  | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 3737 | if (Base && !LVal.getLValueCallIndex() && !Type.isVolatileQualified()) { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3738 | if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(Base)) { | 
|  | 3739 | // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the | 
|  | 3740 | // initializer until now for such expressions. Such an expression can't be | 
|  | 3741 | // an ICE in C, so this only matters for fold. | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3742 | if (Type.isVolatileQualified()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3743 | Info.FFDiag(Conv); | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 3744 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 3745 | } | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3746 | APValue Lit; | 
|  | 3747 | if (!Evaluate(Lit, Info, CLE->getInitializer())) | 
|  | 3748 | return false; | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 3749 | CompleteObject LitObj(LVal.Base, &Lit, Base->getType()); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3750 | return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal, AK); | 
| Alexey Bataev | ec47478 | 2014-10-09 08:45:04 +0000 | [diff] [blame] | 3751 | } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) { | 
| Eli Friedman | 3bf72d7 | 2019-02-08 21:18:46 +0000 | [diff] [blame] | 3752 | // Special-case character extraction so we don't have to construct an | 
|  | 3753 | // APValue for the whole string. | 
| Eli Friedman | 041adb0 | 2019-02-09 02:22:17 +0000 | [diff] [blame] | 3754 | assert(LVal.Designator.Entries.size() <= 1 && | 
| Eli Friedman | 3bf72d7 | 2019-02-08 21:18:46 +0000 | [diff] [blame] | 3755 | "Can only read characters from string literals"); | 
| Eli Friedman | 041adb0 | 2019-02-09 02:22:17 +0000 | [diff] [blame] | 3756 | if (LVal.Designator.Entries.empty()) { | 
|  | 3757 | // Fail for now for LValue to RValue conversion of an array. | 
|  | 3758 | // (This shouldn't show up in C/C++, but it could be triggered by a | 
|  | 3759 | // weird EvaluateAsRValue call from a tool.) | 
|  | 3760 | Info.FFDiag(Conv); | 
|  | 3761 | return false; | 
|  | 3762 | } | 
| Eli Friedman | 3bf72d7 | 2019-02-08 21:18:46 +0000 | [diff] [blame] | 3763 | if (LVal.Designator.isOnePastTheEnd()) { | 
|  | 3764 | if (Info.getLangOpts().CPlusPlus11) | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3765 | Info.FFDiag(Conv, diag::note_constexpr_access_past_end) << AK; | 
| Eli Friedman | 3bf72d7 | 2019-02-08 21:18:46 +0000 | [diff] [blame] | 3766 | else | 
|  | 3767 | Info.FFDiag(Conv); | 
|  | 3768 | return false; | 
|  | 3769 | } | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 3770 | uint64_t CharIndex = LVal.Designator.Entries[0].getAsArrayIndex(); | 
| Eli Friedman | 3bf72d7 | 2019-02-08 21:18:46 +0000 | [diff] [blame] | 3771 | RVal = APValue(extractStringLiteralCharacter(Info, Base, CharIndex)); | 
|  | 3772 | return true; | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 3773 | } | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 3774 | } | 
|  | 3775 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 3776 | CompleteObject Obj = findCompleteObject(Info, Conv, AK, LVal, Type); | 
|  | 3777 | return Obj && extractSubobject(Info, Conv, Obj, LVal.Designator, RVal, AK); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3778 | } | 
|  | 3779 |  | 
|  | 3780 | /// Perform an assignment of Val to LVal. Takes ownership of Val. | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 3781 | static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal, | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3782 | QualType LValType, APValue &Val) { | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3783 | if (LVal.Designator.Invalid) | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3784 | return false; | 
|  | 3785 |  | 
| Aaron Ballman | dd69ef3 | 2014-08-19 15:55:55 +0000 | [diff] [blame] | 3786 | if (!Info.getLangOpts().CPlusPlus14) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3787 | Info.FFDiag(E); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 3788 | return false; | 
|  | 3789 | } | 
|  | 3790 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 3791 | CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType); | 
| Malcolm Parsons | fab3680 | 2018-04-16 08:31:08 +0000 | [diff] [blame] | 3792 | return Obj && modifySubobject(Info, E, Obj, LVal.Designator, Val); | 
|  | 3793 | } | 
|  | 3794 |  | 
|  | 3795 | namespace { | 
|  | 3796 | struct CompoundAssignSubobjectHandler { | 
|  | 3797 | EvalInfo &Info; | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3798 | const Expr *E; | 
|  | 3799 | QualType PromotedLHSType; | 
|  | 3800 | BinaryOperatorKind Opcode; | 
|  | 3801 | const APValue &RHS; | 
|  | 3802 |  | 
|  | 3803 | static const AccessKinds AccessKind = AK_Assign; | 
|  | 3804 |  | 
|  | 3805 | typedef bool result_type; | 
|  | 3806 |  | 
|  | 3807 | bool checkConst(QualType QT) { | 
|  | 3808 | // Assigning to a const object has undefined behavior. | 
|  | 3809 | if (QT.isConstQualified()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3810 | Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3811 | return false; | 
|  | 3812 | } | 
|  | 3813 | return true; | 
|  | 3814 | } | 
|  | 3815 |  | 
|  | 3816 | bool failed() { return false; } | 
|  | 3817 | bool found(APValue &Subobj, QualType SubobjType) { | 
|  | 3818 | switch (Subobj.getKind()) { | 
|  | 3819 | case APValue::Int: | 
|  | 3820 | return found(Subobj.getInt(), SubobjType); | 
|  | 3821 | case APValue::Float: | 
|  | 3822 | return found(Subobj.getFloat(), SubobjType); | 
|  | 3823 | case APValue::ComplexInt: | 
|  | 3824 | case APValue::ComplexFloat: | 
|  | 3825 | // FIXME: Implement complex compound assignment. | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3826 | Info.FFDiag(E); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3827 | return false; | 
|  | 3828 | case APValue::LValue: | 
|  | 3829 | return foundPointer(Subobj, SubobjType); | 
|  | 3830 | default: | 
|  | 3831 | // FIXME: can this happen? | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3832 | Info.FFDiag(E); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3833 | return false; | 
|  | 3834 | } | 
|  | 3835 | } | 
|  | 3836 | bool found(APSInt &Value, QualType SubobjType) { | 
|  | 3837 | if (!checkConst(SubobjType)) | 
|  | 3838 | return false; | 
|  | 3839 |  | 
| Tan S. B. | 9f935e8 | 2018-12-18 07:38:06 +0000 | [diff] [blame] | 3840 | if (!SubobjType->isIntegerType()) { | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3841 | // We don't support compound assignment on integer-cast-to-pointer | 
|  | 3842 | // values. | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3843 | Info.FFDiag(E); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3844 | return false; | 
|  | 3845 | } | 
|  | 3846 |  | 
| Tan S. B. | 9f935e8 | 2018-12-18 07:38:06 +0000 | [diff] [blame] | 3847 | if (RHS.isInt()) { | 
|  | 3848 | APSInt LHS = | 
|  | 3849 | HandleIntToIntCast(Info, E, PromotedLHSType, SubobjType, Value); | 
|  | 3850 | if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS)) | 
|  | 3851 | return false; | 
|  | 3852 | Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS); | 
|  | 3853 | return true; | 
|  | 3854 | } else if (RHS.isFloat()) { | 
|  | 3855 | APFloat FValue(0.0); | 
|  | 3856 | return HandleIntToFloatCast(Info, E, SubobjType, Value, PromotedLHSType, | 
|  | 3857 | FValue) && | 
|  | 3858 | handleFloatFloatBinOp(Info, E, FValue, Opcode, RHS.getFloat()) && | 
|  | 3859 | HandleFloatToIntCast(Info, E, PromotedLHSType, FValue, SubobjType, | 
|  | 3860 | Value); | 
|  | 3861 | } | 
|  | 3862 |  | 
|  | 3863 | Info.FFDiag(E); | 
|  | 3864 | return false; | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3865 | } | 
|  | 3866 | bool found(APFloat &Value, QualType SubobjType) { | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 3867 | return checkConst(SubobjType) && | 
|  | 3868 | HandleFloatToFloatCast(Info, E, SubobjType, PromotedLHSType, | 
|  | 3869 | Value) && | 
|  | 3870 | handleFloatFloatBinOp(Info, E, Value, Opcode, RHS.getFloat()) && | 
|  | 3871 | HandleFloatToFloatCast(Info, E, PromotedLHSType, SubobjType, Value); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3872 | } | 
|  | 3873 | bool foundPointer(APValue &Subobj, QualType SubobjType) { | 
|  | 3874 | if (!checkConst(SubobjType)) | 
|  | 3875 | return false; | 
|  | 3876 |  | 
|  | 3877 | QualType PointeeType; | 
|  | 3878 | if (const PointerType *PT = SubobjType->getAs<PointerType>()) | 
|  | 3879 | PointeeType = PT->getPointeeType(); | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 3880 |  | 
|  | 3881 | if (PointeeType.isNull() || !RHS.isInt() || | 
|  | 3882 | (Opcode != BO_Add && Opcode != BO_Sub)) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3883 | Info.FFDiag(E); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3884 | return false; | 
|  | 3885 | } | 
|  | 3886 |  | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 3887 | APSInt Offset = RHS.getInt(); | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 3888 | if (Opcode == BO_Sub) | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 3889 | negateAsSigned(Offset); | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 3890 |  | 
|  | 3891 | LValue LVal; | 
|  | 3892 | LVal.setFrom(Info.Ctx, Subobj); | 
|  | 3893 | if (!HandleLValueArrayAdjustment(Info, E, LVal, PointeeType, Offset)) | 
|  | 3894 | return false; | 
|  | 3895 | LVal.moveInto(Subobj); | 
|  | 3896 | return true; | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3897 | } | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3898 | }; | 
|  | 3899 | } // end anonymous namespace | 
|  | 3900 |  | 
|  | 3901 | const AccessKinds CompoundAssignSubobjectHandler::AccessKind; | 
|  | 3902 |  | 
|  | 3903 | /// Perform a compound assignment of LVal <op>= RVal. | 
|  | 3904 | static bool handleCompoundAssignment( | 
|  | 3905 | EvalInfo &Info, const Expr *E, | 
|  | 3906 | const LValue &LVal, QualType LValType, QualType PromotedLValType, | 
|  | 3907 | BinaryOperatorKind Opcode, const APValue &RVal) { | 
|  | 3908 | if (LVal.Designator.Invalid) | 
|  | 3909 | return false; | 
|  | 3910 |  | 
| Aaron Ballman | dd69ef3 | 2014-08-19 15:55:55 +0000 | [diff] [blame] | 3911 | if (!Info.getLangOpts().CPlusPlus14) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3912 | Info.FFDiag(E); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 3913 | return false; | 
|  | 3914 | } | 
|  | 3915 |  | 
|  | 3916 | CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType); | 
|  | 3917 | CompoundAssignSubobjectHandler Handler = { Info, E, PromotedLValType, Opcode, | 
|  | 3918 | RVal }; | 
|  | 3919 | return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); | 
|  | 3920 | } | 
|  | 3921 |  | 
| Malcolm Parsons | fab3680 | 2018-04-16 08:31:08 +0000 | [diff] [blame] | 3922 | namespace { | 
|  | 3923 | struct IncDecSubobjectHandler { | 
|  | 3924 | EvalInfo &Info; | 
|  | 3925 | const UnaryOperator *E; | 
|  | 3926 | AccessKinds AccessKind; | 
|  | 3927 | APValue *Old; | 
|  | 3928 |  | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 3929 | typedef bool result_type; | 
|  | 3930 |  | 
|  | 3931 | bool checkConst(QualType QT) { | 
|  | 3932 | // Assigning to a const object has undefined behavior. | 
|  | 3933 | if (QT.isConstQualified()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3934 | Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 3935 | return false; | 
|  | 3936 | } | 
|  | 3937 | return true; | 
|  | 3938 | } | 
|  | 3939 |  | 
|  | 3940 | bool failed() { return false; } | 
|  | 3941 | bool found(APValue &Subobj, QualType SubobjType) { | 
|  | 3942 | // Stash the old value. Also clear Old, so we don't clobber it later | 
|  | 3943 | // if we're post-incrementing a complex. | 
|  | 3944 | if (Old) { | 
|  | 3945 | *Old = Subobj; | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 3946 | Old = nullptr; | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 3947 | } | 
|  | 3948 |  | 
|  | 3949 | switch (Subobj.getKind()) { | 
|  | 3950 | case APValue::Int: | 
|  | 3951 | return found(Subobj.getInt(), SubobjType); | 
|  | 3952 | case APValue::Float: | 
|  | 3953 | return found(Subobj.getFloat(), SubobjType); | 
|  | 3954 | case APValue::ComplexInt: | 
|  | 3955 | return found(Subobj.getComplexIntReal(), | 
|  | 3956 | SubobjType->castAs<ComplexType>()->getElementType() | 
|  | 3957 | .withCVRQualifiers(SubobjType.getCVRQualifiers())); | 
|  | 3958 | case APValue::ComplexFloat: | 
|  | 3959 | return found(Subobj.getComplexFloatReal(), | 
|  | 3960 | SubobjType->castAs<ComplexType>()->getElementType() | 
|  | 3961 | .withCVRQualifiers(SubobjType.getCVRQualifiers())); | 
|  | 3962 | case APValue::LValue: | 
|  | 3963 | return foundPointer(Subobj, SubobjType); | 
|  | 3964 | default: | 
|  | 3965 | // FIXME: can this happen? | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3966 | Info.FFDiag(E); | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 3967 | return false; | 
|  | 3968 | } | 
|  | 3969 | } | 
|  | 3970 | bool found(APSInt &Value, QualType SubobjType) { | 
|  | 3971 | if (!checkConst(SubobjType)) | 
|  | 3972 | return false; | 
|  | 3973 |  | 
|  | 3974 | if (!SubobjType->isIntegerType()) { | 
|  | 3975 | // We don't support increment / decrement on integer-cast-to-pointer | 
|  | 3976 | // values. | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 3977 | Info.FFDiag(E); | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 3978 | return false; | 
|  | 3979 | } | 
|  | 3980 |  | 
|  | 3981 | if (Old) *Old = APValue(Value); | 
|  | 3982 |  | 
|  | 3983 | // bool arithmetic promotes to int, and the conversion back to bool | 
|  | 3984 | // doesn't reduce mod 2^n, so special-case it. | 
|  | 3985 | if (SubobjType->isBooleanType()) { | 
|  | 3986 | if (AccessKind == AK_Increment) | 
|  | 3987 | Value = 1; | 
|  | 3988 | else | 
|  | 3989 | Value = !Value; | 
|  | 3990 | return true; | 
|  | 3991 | } | 
|  | 3992 |  | 
|  | 3993 | bool WasNegative = Value.isNegative(); | 
| Malcolm Parsons | fab3680 | 2018-04-16 08:31:08 +0000 | [diff] [blame] | 3994 | if (AccessKind == AK_Increment) { | 
|  | 3995 | ++Value; | 
|  | 3996 |  | 
|  | 3997 | if (!WasNegative && Value.isNegative() && E->canOverflow()) { | 
|  | 3998 | APSInt ActualValue(Value, /*IsUnsigned*/true); | 
|  | 3999 | return HandleOverflow(Info, E, ActualValue, SubobjType); | 
|  | 4000 | } | 
|  | 4001 | } else { | 
|  | 4002 | --Value; | 
|  | 4003 |  | 
|  | 4004 | if (WasNegative && !Value.isNegative() && E->canOverflow()) { | 
|  | 4005 | unsigned BitWidth = Value.getBitWidth(); | 
|  | 4006 | APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false); | 
|  | 4007 | ActualValue.setBit(BitWidth); | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 4008 | return HandleOverflow(Info, E, ActualValue, SubobjType); | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 4009 | } | 
|  | 4010 | } | 
|  | 4011 | return true; | 
|  | 4012 | } | 
|  | 4013 | bool found(APFloat &Value, QualType SubobjType) { | 
|  | 4014 | if (!checkConst(SubobjType)) | 
|  | 4015 | return false; | 
|  | 4016 |  | 
|  | 4017 | if (Old) *Old = APValue(Value); | 
|  | 4018 |  | 
|  | 4019 | APFloat One(Value.getSemantics(), 1); | 
|  | 4020 | if (AccessKind == AK_Increment) | 
|  | 4021 | Value.add(One, APFloat::rmNearestTiesToEven); | 
|  | 4022 | else | 
|  | 4023 | Value.subtract(One, APFloat::rmNearestTiesToEven); | 
|  | 4024 | return true; | 
|  | 4025 | } | 
|  | 4026 | bool foundPointer(APValue &Subobj, QualType SubobjType) { | 
|  | 4027 | if (!checkConst(SubobjType)) | 
|  | 4028 | return false; | 
|  | 4029 |  | 
|  | 4030 | QualType PointeeType; | 
|  | 4031 | if (const PointerType *PT = SubobjType->getAs<PointerType>()) | 
|  | 4032 | PointeeType = PT->getPointeeType(); | 
|  | 4033 | else { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4034 | Info.FFDiag(E); | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 4035 | return false; | 
|  | 4036 | } | 
|  | 4037 |  | 
|  | 4038 | LValue LVal; | 
|  | 4039 | LVal.setFrom(Info.Ctx, Subobj); | 
|  | 4040 | if (!HandleLValueArrayAdjustment(Info, E, LVal, PointeeType, | 
|  | 4041 | AccessKind == AK_Increment ? 1 : -1)) | 
|  | 4042 | return false; | 
|  | 4043 | LVal.moveInto(Subobj); | 
|  | 4044 | return true; | 
|  | 4045 | } | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 4046 | }; | 
|  | 4047 | } // end anonymous namespace | 
|  | 4048 |  | 
|  | 4049 | /// Perform an increment or decrement on LVal. | 
|  | 4050 | static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal, | 
|  | 4051 | QualType LValType, bool IsIncrement, APValue *Old) { | 
|  | 4052 | if (LVal.Designator.Invalid) | 
|  | 4053 | return false; | 
|  | 4054 |  | 
| Aaron Ballman | dd69ef3 | 2014-08-19 15:55:55 +0000 | [diff] [blame] | 4055 | if (!Info.getLangOpts().CPlusPlus14) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4056 | Info.FFDiag(E); | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 4057 | return false; | 
|  | 4058 | } | 
| Malcolm Parsons | fab3680 | 2018-04-16 08:31:08 +0000 | [diff] [blame] | 4059 |  | 
|  | 4060 | AccessKinds AK = IsIncrement ? AK_Increment : AK_Decrement; | 
|  | 4061 | CompleteObject Obj = findCompleteObject(Info, E, AK, LVal, LValType); | 
|  | 4062 | IncDecSubobjectHandler Handler = {Info, cast<UnaryOperator>(E), AK, Old}; | 
|  | 4063 | return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); | 
|  | 4064 | } | 
|  | 4065 |  | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 4066 | /// Build an lvalue for the object argument of a member function call. | 
|  | 4067 | static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, | 
|  | 4068 | LValue &This) { | 
| Richard Smith | 5e18f4d | 2019-10-02 01:13:57 +0000 | [diff] [blame] | 4069 | if (Object->getType()->isPointerType() && Object->isRValue()) | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 4070 | return EvaluatePointer(Object, This, Info); | 
|  | 4071 |  | 
|  | 4072 | if (Object->isGLValue()) | 
|  | 4073 | return EvaluateLValue(Object, This, Info); | 
|  | 4074 |  | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4075 | if (Object->getType()->isLiteralType(Info.Ctx)) | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4076 | return EvaluateTemporary(Object, This, Info); | 
|  | 4077 |  | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4078 | Info.FFDiag(Object, diag::note_constexpr_nonliteral) << Object->getType(); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4079 | return false; | 
|  | 4080 | } | 
|  | 4081 |  | 
|  | 4082 | /// HandleMemberPointerAccess - Evaluate a member access operation and build an | 
|  | 4083 | /// lvalue referring to the result. | 
|  | 4084 | /// | 
|  | 4085 | /// \param Info - Information about the ongoing evaluation. | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4086 | /// \param LV - An lvalue referring to the base of the member pointer. | 
|  | 4087 | /// \param RHS - The member pointer expression. | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4088 | /// \param IncludeMember - Specifies whether the member itself is included in | 
|  | 4089 | ///        the resulting LValue subobject designator. This is not possible when | 
|  | 4090 | ///        creating a bound member function. | 
|  | 4091 | /// \return The field or method declaration to which the member pointer refers, | 
|  | 4092 | ///         or 0 if evaluation fails. | 
|  | 4093 | static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4094 | QualType LVType, | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4095 | LValue &LV, | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4096 | const Expr *RHS, | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4097 | bool IncludeMember = true) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4098 | MemberPtr MemPtr; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4099 | if (!EvaluateMemberPointer(RHS, MemPtr, Info)) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4100 | return nullptr; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4101 |  | 
|  | 4102 | // C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to | 
|  | 4103 | // member value, the behavior is undefined. | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4104 | if (!MemPtr.getDecl()) { | 
|  | 4105 | // FIXME: Specific diagnostic. | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4106 | Info.FFDiag(RHS); | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4107 | return nullptr; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4108 | } | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 4109 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4110 | if (MemPtr.isDerivedMember()) { | 
|  | 4111 | // This is a member of some derived class. Truncate LV appropriately. | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4112 | // The end of the derived-to-base path for the base object must match the | 
|  | 4113 | // derived-to-base path for the member pointer. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4114 | if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() > | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4115 | LV.Designator.Entries.size()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4116 | Info.FFDiag(RHS); | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4117 | return nullptr; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4118 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4119 | unsigned PathLengthToMember = | 
|  | 4120 | LV.Designator.Entries.size() - MemPtr.Path.size(); | 
|  | 4121 | for (unsigned I = 0, N = MemPtr.Path.size(); I != N; ++I) { | 
|  | 4122 | const CXXRecordDecl *LVDecl = getAsBaseClass( | 
|  | 4123 | LV.Designator.Entries[PathLengthToMember + I]); | 
|  | 4124 | const CXXRecordDecl *MPDecl = MemPtr.Path[I]; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4125 | if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4126 | Info.FFDiag(RHS); | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4127 | return nullptr; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4128 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4129 | } | 
|  | 4130 |  | 
|  | 4131 | // Truncate the lvalue to the appropriate derived class. | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4132 | if (!CastToDerivedClass(Info, RHS, LV, MemPtr.getContainingRecord(), | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4133 | PathLengthToMember)) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4134 | return nullptr; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4135 | } else if (!MemPtr.Path.empty()) { | 
|  | 4136 | // Extend the LValue path with the member pointer's path. | 
|  | 4137 | LV.Designator.Entries.reserve(LV.Designator.Entries.size() + | 
|  | 4138 | MemPtr.Path.size() + IncludeMember); | 
|  | 4139 |  | 
|  | 4140 | // Walk down to the appropriate base class. | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4141 | if (const PointerType *PT = LVType->getAs<PointerType>()) | 
|  | 4142 | LVType = PT->getPointeeType(); | 
|  | 4143 | const CXXRecordDecl *RD = LVType->getAsCXXRecordDecl(); | 
|  | 4144 | assert(RD && "member pointer access on non-class-type expression"); | 
|  | 4145 | // The first class in the path is that of the lvalue. | 
|  | 4146 | for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) { | 
|  | 4147 | const CXXRecordDecl *Base = MemPtr.Path[N - I - 1]; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4148 | if (!HandleLValueDirectBase(Info, RHS, LV, RD, Base)) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4149 | return nullptr; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4150 | RD = Base; | 
|  | 4151 | } | 
|  | 4152 | // Finally cast to the class containing the member. | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4153 | if (!HandleLValueDirectBase(Info, RHS, LV, RD, | 
|  | 4154 | MemPtr.getContainingRecord())) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4155 | return nullptr; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4156 | } | 
|  | 4157 |  | 
|  | 4158 | // Add the member. Note that we cannot build bound member functions here. | 
|  | 4159 | if (IncludeMember) { | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 4160 | if (const FieldDecl *FD = dyn_cast<FieldDecl>(MemPtr.getDecl())) { | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4161 | if (!HandleLValueMember(Info, RHS, LV, FD)) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4162 | return nullptr; | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 4163 | } else if (const IndirectFieldDecl *IFD = | 
|  | 4164 | dyn_cast<IndirectFieldDecl>(MemPtr.getDecl())) { | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4165 | if (!HandleLValueIndirectMember(Info, RHS, LV, IFD)) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4166 | return nullptr; | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 4167 | } else { | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 4168 | llvm_unreachable("can't construct reference to bound member function"); | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 4169 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4170 | } | 
|  | 4171 |  | 
|  | 4172 | return MemPtr.getDecl(); | 
|  | 4173 | } | 
|  | 4174 |  | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4175 | static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, | 
|  | 4176 | const BinaryOperator *BO, | 
|  | 4177 | LValue &LV, | 
|  | 4178 | bool IncludeMember = true) { | 
|  | 4179 | assert(BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI); | 
|  | 4180 |  | 
|  | 4181 | if (!EvaluateObjectArgument(Info, BO->getLHS(), LV)) { | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 4182 | if (Info.noteFailure()) { | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4183 | MemberPtr MemPtr; | 
|  | 4184 | EvaluateMemberPointer(BO->getRHS(), MemPtr, Info); | 
|  | 4185 | } | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4186 | return nullptr; | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 4187 | } | 
|  | 4188 |  | 
|  | 4189 | return HandleMemberPointerAccess(Info, BO->getLHS()->getType(), LV, | 
|  | 4190 | BO->getRHS(), IncludeMember); | 
|  | 4191 | } | 
|  | 4192 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4193 | /// HandleBaseToDerivedCast - Apply the given base-to-derived cast operation on | 
|  | 4194 | /// the provided lvalue, which currently refers to the base object. | 
|  | 4195 | static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E, | 
|  | 4196 | LValue &Result) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4197 | SubobjectDesignator &D = Result.Designator; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4198 | if (D.Invalid || !Result.checkNullPointer(Info, E, CSK_Derived)) | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4199 | return false; | 
|  | 4200 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4201 | QualType TargetQT = E->getType(); | 
|  | 4202 | if (const PointerType *PT = TargetQT->getAs<PointerType>()) | 
|  | 4203 | TargetQT = PT->getPointeeType(); | 
|  | 4204 |  | 
|  | 4205 | // Check this cast lands within the final derived-to-base subobject path. | 
|  | 4206 | if (D.MostDerivedPathLength + E->path_size() > D.Entries.size()) { | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 4207 | Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4208 | << D.MostDerivedType << TargetQT; | 
|  | 4209 | return false; | 
|  | 4210 | } | 
|  | 4211 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4212 | // Check the type of the final cast. We don't need to check the path, | 
|  | 4213 | // since a cast can only be formed if the path is unique. | 
|  | 4214 | unsigned NewEntriesSize = D.Entries.size() - E->path_size(); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4215 | const CXXRecordDecl *TargetType = TargetQT->getAsCXXRecordDecl(); | 
|  | 4216 | const CXXRecordDecl *FinalType; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4217 | if (NewEntriesSize == D.MostDerivedPathLength) | 
|  | 4218 | FinalType = D.MostDerivedType->getAsCXXRecordDecl(); | 
|  | 4219 | else | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4220 | FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4221 | if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) { | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 4222 | Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4223 | << D.MostDerivedType << TargetQT; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4224 | return false; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4225 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 4226 |  | 
|  | 4227 | // Truncate the lvalue to the appropriate derived class. | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 4228 | return CastToDerivedClass(Info, E, Result, TargetType, NewEntriesSize); | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 4229 | } | 
|  | 4230 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 4231 | /// Get the value to use for a default-initialized object of type T. | 
|  | 4232 | static APValue getDefaultInitValue(QualType T) { | 
|  | 4233 | if (auto *RD = T->getAsCXXRecordDecl()) { | 
|  | 4234 | if (RD->isUnion()) | 
|  | 4235 | return APValue((const FieldDecl*)nullptr); | 
|  | 4236 |  | 
|  | 4237 | APValue Struct(APValue::UninitStruct(), RD->getNumBases(), | 
|  | 4238 | std::distance(RD->field_begin(), RD->field_end())); | 
|  | 4239 |  | 
|  | 4240 | unsigned Index = 0; | 
|  | 4241 | for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), | 
|  | 4242 | End = RD->bases_end(); I != End; ++I, ++Index) | 
|  | 4243 | Struct.getStructBase(Index) = getDefaultInitValue(I->getType()); | 
|  | 4244 |  | 
|  | 4245 | for (const auto *I : RD->fields()) { | 
|  | 4246 | if (I->isUnnamedBitfield()) | 
|  | 4247 | continue; | 
|  | 4248 | Struct.getStructField(I->getFieldIndex()) = | 
|  | 4249 | getDefaultInitValue(I->getType()); | 
|  | 4250 | } | 
|  | 4251 | return Struct; | 
|  | 4252 | } | 
|  | 4253 |  | 
|  | 4254 | if (auto *AT = | 
|  | 4255 | dyn_cast_or_null<ConstantArrayType>(T->getAsArrayTypeUnsafe())) { | 
|  | 4256 | APValue Array(APValue::UninitArray(), 0, AT->getSize().getZExtValue()); | 
|  | 4257 | if (Array.hasArrayFiller()) | 
|  | 4258 | Array.getArrayFiller() = getDefaultInitValue(AT->getElementType()); | 
|  | 4259 | return Array; | 
|  | 4260 | } | 
|  | 4261 |  | 
|  | 4262 | return APValue::IndeterminateValue(); | 
|  | 4263 | } | 
|  | 4264 |  | 
| Mike Stump | 876387b | 2009-10-27 22:09:17 +0000 | [diff] [blame] | 4265 | namespace { | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4266 | enum EvalStmtResult { | 
|  | 4267 | /// Evaluation failed. | 
|  | 4268 | ESR_Failed, | 
|  | 4269 | /// Hit a 'return' statement. | 
|  | 4270 | ESR_Returned, | 
|  | 4271 | /// Evaluation succeeded. | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4272 | ESR_Succeeded, | 
|  | 4273 | /// Hit a 'continue' statement. | 
|  | 4274 | ESR_Continue, | 
|  | 4275 | /// Hit a 'break' statement. | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4276 | ESR_Break, | 
|  | 4277 | /// Still scanning for 'case' or 'default' statement. | 
|  | 4278 | ESR_CaseNotFound | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4279 | }; | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 4280 | } | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4281 |  | 
| Richard Smith | 97fcf4b | 2016-08-14 23:15:52 +0000 | [diff] [blame] | 4282 | static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { | 
|  | 4283 | // We don't need to evaluate the initializer for a static local. | 
|  | 4284 | if (!VD->hasLocalStorage()) | 
|  | 4285 | return true; | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4286 |  | 
| Richard Smith | 97fcf4b | 2016-08-14 23:15:52 +0000 | [diff] [blame] | 4287 | LValue Result; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4288 | APValue &Val = | 
|  | 4289 | Info.CurrentCall->createTemporary(VD, VD->getType(), true, Result); | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4290 |  | 
| Richard Smith | 97fcf4b | 2016-08-14 23:15:52 +0000 | [diff] [blame] | 4291 | const Expr *InitE = VD->getInit(); | 
|  | 4292 | if (!InitE) { | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 4293 | Val = getDefaultInitValue(VD->getType()); | 
|  | 4294 | return true; | 
| Richard Smith | 97fcf4b | 2016-08-14 23:15:52 +0000 | [diff] [blame] | 4295 | } | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 4296 |  | 
| Richard Smith | 97fcf4b | 2016-08-14 23:15:52 +0000 | [diff] [blame] | 4297 | if (InitE->isValueDependent()) | 
|  | 4298 | return false; | 
| Argyrios Kyrtzidis | 3d9e382 | 2014-02-20 04:00:01 +0000 | [diff] [blame] | 4299 |  | 
| Richard Smith | 97fcf4b | 2016-08-14 23:15:52 +0000 | [diff] [blame] | 4300 | if (!EvaluateInPlace(Val, Info, Result, InitE)) { | 
|  | 4301 | // Wipe out any partially-computed value, to allow tracking that this | 
|  | 4302 | // evaluation failed. | 
|  | 4303 | Val = APValue(); | 
|  | 4304 | return false; | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4305 | } | 
|  | 4306 |  | 
|  | 4307 | return true; | 
|  | 4308 | } | 
|  | 4309 |  | 
| Richard Smith | 97fcf4b | 2016-08-14 23:15:52 +0000 | [diff] [blame] | 4310 | static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { | 
|  | 4311 | bool OK = true; | 
|  | 4312 |  | 
|  | 4313 | if (const VarDecl *VD = dyn_cast<VarDecl>(D)) | 
|  | 4314 | OK &= EvaluateVarDecl(Info, VD); | 
|  | 4315 |  | 
|  | 4316 | if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(D)) | 
|  | 4317 | for (auto *BD : DD->bindings()) | 
|  | 4318 | if (auto *VD = BD->getHoldingVar()) | 
|  | 4319 | OK &= EvaluateDecl(Info, VD); | 
|  | 4320 |  | 
|  | 4321 | return OK; | 
|  | 4322 | } | 
|  | 4323 |  | 
|  | 4324 |  | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4325 | /// Evaluate a condition (either a variable declaration or an expression). | 
|  | 4326 | static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, | 
|  | 4327 | const Expr *Cond, bool &Result) { | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4328 | FullExpressionRAII Scope(Info); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4329 | if (CondDecl && !EvaluateDecl(Info, CondDecl)) | 
|  | 4330 | return false; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4331 | if (!EvaluateAsBooleanCondition(Cond, Result, Info)) | 
|  | 4332 | return false; | 
|  | 4333 | return Scope.destroy(); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4334 | } | 
|  | 4335 |  | 
| Richard Smith | 8921007 | 2016-04-04 23:29:43 +0000 | [diff] [blame] | 4336 | namespace { | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 4337 | /// A location where the result (returned value) of evaluating a | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 4338 | /// statement should be stored. | 
|  | 4339 | struct StmtResult { | 
|  | 4340 | /// The APValue that should be filled in with the returned value. | 
|  | 4341 | APValue &Value; | 
|  | 4342 | /// The location containing the result, if any (used to support RVO). | 
|  | 4343 | const LValue *Slot; | 
|  | 4344 | }; | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 4345 |  | 
|  | 4346 | struct TempVersionRAII { | 
|  | 4347 | CallStackFrame &Frame; | 
|  | 4348 |  | 
|  | 4349 | TempVersionRAII(CallStackFrame &Frame) : Frame(Frame) { | 
|  | 4350 | Frame.pushTempVersion(); | 
|  | 4351 | } | 
|  | 4352 |  | 
|  | 4353 | ~TempVersionRAII() { | 
|  | 4354 | Frame.popTempVersion(); | 
|  | 4355 | } | 
|  | 4356 | }; | 
|  | 4357 |  | 
| Richard Smith | 8921007 | 2016-04-04 23:29:43 +0000 | [diff] [blame] | 4358 | } | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 4359 |  | 
|  | 4360 | static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4361 | const Stmt *S, | 
|  | 4362 | const SwitchCase *SC = nullptr); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4363 |  | 
|  | 4364 | /// Evaluate the body of a loop, and translate the result as appropriate. | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 4365 | static EvalStmtResult EvaluateLoopBody(StmtResult &Result, EvalInfo &Info, | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4366 | const Stmt *Body, | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4367 | const SwitchCase *Case = nullptr) { | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4368 | BlockScopeRAII Scope(Info); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4369 |  | 
|  | 4370 | EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case); | 
|  | 4371 | if (ESR != ESR_Failed && ESR != ESR_CaseNotFound && !Scope.destroy()) | 
|  | 4372 | ESR = ESR_Failed; | 
|  | 4373 |  | 
|  | 4374 | switch (ESR) { | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4375 | case ESR_Break: | 
|  | 4376 | return ESR_Succeeded; | 
|  | 4377 | case ESR_Succeeded: | 
|  | 4378 | case ESR_Continue: | 
|  | 4379 | return ESR_Continue; | 
|  | 4380 | case ESR_Failed: | 
|  | 4381 | case ESR_Returned: | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4382 | case ESR_CaseNotFound: | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4383 | return ESR; | 
|  | 4384 | } | 
| Hans Wennborg | 9242bd1 | 2013-05-06 15:13:34 +0000 | [diff] [blame] | 4385 | llvm_unreachable("Invalid EvalStmtResult!"); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4386 | } | 
|  | 4387 |  | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4388 | /// Evaluate a switch statement. | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 4389 | static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4390 | const SwitchStmt *SS) { | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4391 | BlockScopeRAII Scope(Info); | 
|  | 4392 |  | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4393 | // Evaluate the switch condition. | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4394 | APSInt Value; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4395 | { | 
| Richard Smith | a547eb2 | 2016-07-14 00:11:03 +0000 | [diff] [blame] | 4396 | if (const Stmt *Init = SS->getInit()) { | 
|  | 4397 | EvalStmtResult ESR = EvaluateStmt(Result, Info, Init); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4398 | if (ESR != ESR_Succeeded) { | 
|  | 4399 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4400 | ESR = ESR_Failed; | 
| Richard Smith | a547eb2 | 2016-07-14 00:11:03 +0000 | [diff] [blame] | 4401 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4402 | } | 
| Richard Smith | a547eb2 | 2016-07-14 00:11:03 +0000 | [diff] [blame] | 4403 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4404 |  | 
|  | 4405 | FullExpressionRAII CondScope(Info); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4406 | if (SS->getConditionVariable() && | 
|  | 4407 | !EvaluateDecl(Info, SS->getConditionVariable())) | 
|  | 4408 | return ESR_Failed; | 
|  | 4409 | if (!EvaluateInteger(SS->getCond(), Value, Info)) | 
|  | 4410 | return ESR_Failed; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4411 | if (!CondScope.destroy()) | 
|  | 4412 | return ESR_Failed; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4413 | } | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4414 |  | 
|  | 4415 | // Find the switch case corresponding to the value of the condition. | 
|  | 4416 | // FIXME: Cache this lookup. | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4417 | const SwitchCase *Found = nullptr; | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4418 | for (const SwitchCase *SC = SS->getSwitchCaseList(); SC; | 
|  | 4419 | SC = SC->getNextSwitchCase()) { | 
|  | 4420 | if (isa<DefaultStmt>(SC)) { | 
|  | 4421 | Found = SC; | 
|  | 4422 | continue; | 
|  | 4423 | } | 
|  | 4424 |  | 
|  | 4425 | const CaseStmt *CS = cast<CaseStmt>(SC); | 
|  | 4426 | APSInt LHS = CS->getLHS()->EvaluateKnownConstInt(Info.Ctx); | 
|  | 4427 | APSInt RHS = CS->getRHS() ? CS->getRHS()->EvaluateKnownConstInt(Info.Ctx) | 
|  | 4428 | : LHS; | 
|  | 4429 | if (LHS <= Value && Value <= RHS) { | 
|  | 4430 | Found = SC; | 
|  | 4431 | break; | 
|  | 4432 | } | 
|  | 4433 | } | 
|  | 4434 |  | 
|  | 4435 | if (!Found) | 
| Richard Smith | 61dadfc | 2019-10-15 22:23:11 +0000 | [diff] [blame] | 4436 | return Scope.destroy() ? ESR_Succeeded : ESR_Failed; | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4437 |  | 
|  | 4438 | // Search the switch body for the switch case and evaluate it from there. | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4439 | EvalStmtResult ESR = EvaluateStmt(Result, Info, SS->getBody(), Found); | 
|  | 4440 | if (ESR != ESR_Failed && ESR != ESR_CaseNotFound && !Scope.destroy()) | 
|  | 4441 | return ESR_Failed; | 
|  | 4442 |  | 
|  | 4443 | switch (ESR) { | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4444 | case ESR_Break: | 
|  | 4445 | return ESR_Succeeded; | 
|  | 4446 | case ESR_Succeeded: | 
|  | 4447 | case ESR_Continue: | 
|  | 4448 | case ESR_Failed: | 
|  | 4449 | case ESR_Returned: | 
|  | 4450 | return ESR; | 
|  | 4451 | case ESR_CaseNotFound: | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 4452 | // This can only happen if the switch case is nested within a statement | 
|  | 4453 | // expression. We have no intention of supporting that. | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 4454 | Info.FFDiag(Found->getBeginLoc(), | 
|  | 4455 | diag::note_constexpr_stmt_expr_unsupported); | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 4456 | return ESR_Failed; | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4457 | } | 
| Richard Smith | f8cf9d4 | 2013-05-13 20:33:30 +0000 | [diff] [blame] | 4458 | llvm_unreachable("Invalid EvalStmtResult!"); | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4459 | } | 
|  | 4460 |  | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4461 | // Evaluate a statement. | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 4462 | static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4463 | const Stmt *S, const SwitchCase *Case) { | 
| Richard Smith | a3d3bd2 | 2013-05-08 02:12:03 +0000 | [diff] [blame] | 4464 | if (!Info.nextStep(S)) | 
|  | 4465 | return ESR_Failed; | 
|  | 4466 |  | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4467 | // If we're hunting down a 'case' or 'default' label, recurse through | 
|  | 4468 | // substatements until we hit the label. | 
|  | 4469 | if (Case) { | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4470 | switch (S->getStmtClass()) { | 
|  | 4471 | case Stmt::CompoundStmtClass: | 
|  | 4472 | // FIXME: Precompute which substatement of a compound statement we | 
|  | 4473 | // would jump to, and go straight there rather than performing a | 
|  | 4474 | // linear scan each time. | 
|  | 4475 | case Stmt::LabelStmtClass: | 
|  | 4476 | case Stmt::AttributedStmtClass: | 
|  | 4477 | case Stmt::DoStmtClass: | 
|  | 4478 | break; | 
|  | 4479 |  | 
|  | 4480 | case Stmt::CaseStmtClass: | 
|  | 4481 | case Stmt::DefaultStmtClass: | 
|  | 4482 | if (Case == S) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4483 | Case = nullptr; | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4484 | break; | 
|  | 4485 |  | 
|  | 4486 | case Stmt::IfStmtClass: { | 
|  | 4487 | // FIXME: Precompute which side of an 'if' we would jump to, and go | 
|  | 4488 | // straight there rather than scanning both sides. | 
|  | 4489 | const IfStmt *IS = cast<IfStmt>(S); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4490 |  | 
|  | 4491 | // Wrap the evaluation in a block scope, in case it's a DeclStmt | 
|  | 4492 | // preceded by our switch label. | 
|  | 4493 | BlockScopeRAII Scope(Info); | 
|  | 4494 |  | 
| Richard Smith | 397a686 | 2019-09-20 23:08:59 +0000 | [diff] [blame] | 4495 | // Step into the init statement in case it brings an (uninitialized) | 
|  | 4496 | // variable into scope. | 
|  | 4497 | if (const Stmt *Init = IS->getInit()) { | 
|  | 4498 | EvalStmtResult ESR = EvaluateStmt(Result, Info, Init, Case); | 
|  | 4499 | if (ESR != ESR_CaseNotFound) { | 
|  | 4500 | assert(ESR != ESR_Succeeded); | 
|  | 4501 | return ESR; | 
|  | 4502 | } | 
|  | 4503 | } | 
|  | 4504 |  | 
|  | 4505 | // Condition variable must be initialized if it exists. | 
|  | 4506 | // FIXME: We can skip evaluating the body if there's a condition | 
|  | 4507 | // variable, as there can't be any case labels within it. | 
|  | 4508 | // (The same is true for 'for' statements.) | 
|  | 4509 |  | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4510 | EvalStmtResult ESR = EvaluateStmt(Result, Info, IS->getThen(), Case); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4511 | if (ESR == ESR_Failed) | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4512 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4513 | if (ESR != ESR_CaseNotFound) | 
|  | 4514 | return Scope.destroy() ? ESR : ESR_Failed; | 
|  | 4515 | if (!IS->getElse()) | 
|  | 4516 | return ESR_CaseNotFound; | 
|  | 4517 |  | 
|  | 4518 | ESR = EvaluateStmt(Result, Info, IS->getElse(), Case); | 
|  | 4519 | if (ESR == ESR_Failed) | 
|  | 4520 | return ESR; | 
|  | 4521 | if (ESR != ESR_CaseNotFound) | 
|  | 4522 | return Scope.destroy() ? ESR : ESR_Failed; | 
|  | 4523 | return ESR_CaseNotFound; | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4524 | } | 
|  | 4525 |  | 
|  | 4526 | case Stmt::WhileStmtClass: { | 
|  | 4527 | EvalStmtResult ESR = | 
|  | 4528 | EvaluateLoopBody(Result, Info, cast<WhileStmt>(S)->getBody(), Case); | 
|  | 4529 | if (ESR != ESR_Continue) | 
|  | 4530 | return ESR; | 
|  | 4531 | break; | 
|  | 4532 | } | 
|  | 4533 |  | 
|  | 4534 | case Stmt::ForStmtClass: { | 
|  | 4535 | const ForStmt *FS = cast<ForStmt>(S); | 
| Richard Smith | 397a686 | 2019-09-20 23:08:59 +0000 | [diff] [blame] | 4536 | BlockScopeRAII Scope(Info); | 
|  | 4537 |  | 
|  | 4538 | // Step into the init statement in case it brings an (uninitialized) | 
|  | 4539 | // variable into scope. | 
|  | 4540 | if (const Stmt *Init = FS->getInit()) { | 
|  | 4541 | EvalStmtResult ESR = EvaluateStmt(Result, Info, Init, Case); | 
|  | 4542 | if (ESR != ESR_CaseNotFound) { | 
|  | 4543 | assert(ESR != ESR_Succeeded); | 
|  | 4544 | return ESR; | 
|  | 4545 | } | 
|  | 4546 | } | 
|  | 4547 |  | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4548 | EvalStmtResult ESR = | 
|  | 4549 | EvaluateLoopBody(Result, Info, FS->getBody(), Case); | 
|  | 4550 | if (ESR != ESR_Continue) | 
|  | 4551 | return ESR; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4552 | if (FS->getInc()) { | 
|  | 4553 | FullExpressionRAII IncScope(Info); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4554 | if (!EvaluateIgnoredValue(Info, FS->getInc()) || !IncScope.destroy()) | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4555 | return ESR_Failed; | 
|  | 4556 | } | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4557 | break; | 
|  | 4558 | } | 
|  | 4559 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 4560 | case Stmt::DeclStmtClass: { | 
|  | 4561 | // Start the lifetime of any uninitialized variables we encounter. They | 
|  | 4562 | // might be used by the selected branch of the switch. | 
|  | 4563 | const DeclStmt *DS = cast<DeclStmt>(S); | 
|  | 4564 | for (const auto *D : DS->decls()) { | 
|  | 4565 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | 
|  | 4566 | if (VD->hasLocalStorage() && !VD->getInit()) | 
|  | 4567 | if (!EvaluateVarDecl(Info, VD)) | 
|  | 4568 | return ESR_Failed; | 
|  | 4569 | // FIXME: If the variable has initialization that can't be jumped | 
|  | 4570 | // over, bail out of any immediately-surrounding compound-statement | 
|  | 4571 | // too. There can't be any case labels here. | 
|  | 4572 | } | 
|  | 4573 | } | 
|  | 4574 | return ESR_CaseNotFound; | 
|  | 4575 | } | 
|  | 4576 |  | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4577 | default: | 
|  | 4578 | return ESR_CaseNotFound; | 
|  | 4579 | } | 
|  | 4580 | } | 
|  | 4581 |  | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4582 | switch (S->getStmtClass()) { | 
|  | 4583 | default: | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4584 | if (const Expr *E = dyn_cast<Expr>(S)) { | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4585 | // Don't bother evaluating beyond an expression-statement which couldn't | 
|  | 4586 | // be evaluated. | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4587 | // FIXME: Do we need the FullExpressionRAII object here? | 
|  | 4588 | // VisitExprWithCleanups should create one when necessary. | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4589 | FullExpressionRAII Scope(Info); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4590 | if (!EvaluateIgnoredValue(Info, E) || !Scope.destroy()) | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4591 | return ESR_Failed; | 
|  | 4592 | return ESR_Succeeded; | 
|  | 4593 | } | 
|  | 4594 |  | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 4595 | Info.FFDiag(S->getBeginLoc()); | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4596 | return ESR_Failed; | 
|  | 4597 |  | 
|  | 4598 | case Stmt::NullStmtClass: | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4599 | return ESR_Succeeded; | 
|  | 4600 |  | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4601 | case Stmt::DeclStmtClass: { | 
|  | 4602 | const DeclStmt *DS = cast<DeclStmt>(S); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 4603 | for (const auto *D : DS->decls()) { | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4604 | // Each declaration initialization is its own full-expression. | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4605 | FullExpressionRAII Scope(Info); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 4606 | if (!EvaluateDecl(Info, D) && !Info.noteFailure()) | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4607 | return ESR_Failed; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4608 | if (!Scope.destroy()) | 
|  | 4609 | return ESR_Failed; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4610 | } | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4611 | return ESR_Succeeded; | 
|  | 4612 | } | 
|  | 4613 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4614 | case Stmt::ReturnStmtClass: { | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4615 | const Expr *RetExpr = cast<ReturnStmt>(S)->getRetValue(); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4616 | FullExpressionRAII Scope(Info); | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 4617 | if (RetExpr && | 
|  | 4618 | !(Result.Slot | 
|  | 4619 | ? EvaluateInPlace(Result.Value, Info, *Result.Slot, RetExpr) | 
|  | 4620 | : Evaluate(Result.Value, Info, RetExpr))) | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4621 | return ESR_Failed; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4622 | return Scope.destroy() ? ESR_Returned : ESR_Failed; | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4623 | } | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4624 |  | 
|  | 4625 | case Stmt::CompoundStmtClass: { | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4626 | BlockScopeRAII Scope(Info); | 
|  | 4627 |  | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4628 | const CompoundStmt *CS = cast<CompoundStmt>(S); | 
| Aaron Ballman | c7e4e21 | 2014-03-17 14:19:37 +0000 | [diff] [blame] | 4629 | for (const auto *BI : CS->body()) { | 
|  | 4630 | EvalStmtResult ESR = EvaluateStmt(Result, Info, BI, Case); | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4631 | if (ESR == ESR_Succeeded) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4632 | Case = nullptr; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4633 | else if (ESR != ESR_CaseNotFound) { | 
|  | 4634 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4635 | return ESR_Failed; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4636 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4637 | } | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4638 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4639 | if (Case) | 
|  | 4640 | return ESR_CaseNotFound; | 
|  | 4641 | return Scope.destroy() ? ESR_Succeeded : ESR_Failed; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4642 | } | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4643 |  | 
|  | 4644 | case Stmt::IfStmtClass: { | 
|  | 4645 | const IfStmt *IS = cast<IfStmt>(S); | 
|  | 4646 |  | 
|  | 4647 | // Evaluate the condition, as either a var decl or as an expression. | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4648 | BlockScopeRAII Scope(Info); | 
| Richard Smith | a547eb2 | 2016-07-14 00:11:03 +0000 | [diff] [blame] | 4649 | if (const Stmt *Init = IS->getInit()) { | 
|  | 4650 | EvalStmtResult ESR = EvaluateStmt(Result, Info, Init); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4651 | if (ESR != ESR_Succeeded) { | 
|  | 4652 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4653 | return ESR_Failed; | 
| Richard Smith | a547eb2 | 2016-07-14 00:11:03 +0000 | [diff] [blame] | 4654 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4655 | } | 
| Richard Smith | a547eb2 | 2016-07-14 00:11:03 +0000 | [diff] [blame] | 4656 | } | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4657 | bool Cond; | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4658 | if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(), Cond)) | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4659 | return ESR_Failed; | 
|  | 4660 |  | 
|  | 4661 | if (const Stmt *SubStmt = Cond ? IS->getThen() : IS->getElse()) { | 
|  | 4662 | EvalStmtResult ESR = EvaluateStmt(Result, Info, SubStmt); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4663 | if (ESR != ESR_Succeeded) { | 
|  | 4664 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4665 | return ESR_Failed; | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4666 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4667 | } | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4668 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4669 | return Scope.destroy() ? ESR_Succeeded : ESR_Failed; | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 4670 | } | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4671 |  | 
|  | 4672 | case Stmt::WhileStmtClass: { | 
|  | 4673 | const WhileStmt *WS = cast<WhileStmt>(S); | 
|  | 4674 | while (true) { | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4675 | BlockScopeRAII Scope(Info); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4676 | bool Continue; | 
|  | 4677 | if (!EvaluateCond(Info, WS->getConditionVariable(), WS->getCond(), | 
|  | 4678 | Continue)) | 
|  | 4679 | return ESR_Failed; | 
|  | 4680 | if (!Continue) | 
|  | 4681 | break; | 
|  | 4682 |  | 
|  | 4683 | EvalStmtResult ESR = EvaluateLoopBody(Result, Info, WS->getBody()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4684 | if (ESR != ESR_Continue) { | 
|  | 4685 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4686 | return ESR_Failed; | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4687 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4688 | } | 
|  | 4689 | if (!Scope.destroy()) | 
|  | 4690 | return ESR_Failed; | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4691 | } | 
|  | 4692 | return ESR_Succeeded; | 
|  | 4693 | } | 
|  | 4694 |  | 
|  | 4695 | case Stmt::DoStmtClass: { | 
|  | 4696 | const DoStmt *DS = cast<DoStmt>(S); | 
|  | 4697 | bool Continue; | 
|  | 4698 | do { | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4699 | EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4700 | if (ESR != ESR_Continue) | 
|  | 4701 | return ESR; | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 4702 | Case = nullptr; | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4703 |  | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4704 | FullExpressionRAII CondScope(Info); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4705 | if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info) || | 
|  | 4706 | !CondScope.destroy()) | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4707 | return ESR_Failed; | 
|  | 4708 | } while (Continue); | 
|  | 4709 | return ESR_Succeeded; | 
|  | 4710 | } | 
|  | 4711 |  | 
|  | 4712 | case Stmt::ForStmtClass: { | 
|  | 4713 | const ForStmt *FS = cast<ForStmt>(S); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4714 | BlockScopeRAII ForScope(Info); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4715 | if (FS->getInit()) { | 
|  | 4716 | EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getInit()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4717 | if (ESR != ESR_Succeeded) { | 
|  | 4718 | if (ESR != ESR_Failed && !ForScope.destroy()) | 
|  | 4719 | return ESR_Failed; | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4720 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4721 | } | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4722 | } | 
|  | 4723 | while (true) { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4724 | BlockScopeRAII IterScope(Info); | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4725 | bool Continue = true; | 
|  | 4726 | if (FS->getCond() && !EvaluateCond(Info, FS->getConditionVariable(), | 
|  | 4727 | FS->getCond(), Continue)) | 
|  | 4728 | return ESR_Failed; | 
|  | 4729 | if (!Continue) | 
|  | 4730 | break; | 
|  | 4731 |  | 
|  | 4732 | EvalStmtResult ESR = EvaluateLoopBody(Result, Info, FS->getBody()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4733 | if (ESR != ESR_Continue) { | 
|  | 4734 | if (ESR != ESR_Failed && (!IterScope.destroy() || !ForScope.destroy())) | 
|  | 4735 | return ESR_Failed; | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4736 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4737 | } | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4738 |  | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4739 | if (FS->getInc()) { | 
|  | 4740 | FullExpressionRAII IncScope(Info); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4741 | if (!EvaluateIgnoredValue(Info, FS->getInc()) || !IncScope.destroy()) | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4742 | return ESR_Failed; | 
|  | 4743 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4744 |  | 
|  | 4745 | if (!IterScope.destroy()) | 
|  | 4746 | return ESR_Failed; | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4747 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4748 | return ForScope.destroy() ? ESR_Succeeded : ESR_Failed; | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4749 | } | 
|  | 4750 |  | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4751 | case Stmt::CXXForRangeStmtClass: { | 
|  | 4752 | const CXXForRangeStmt *FS = cast<CXXForRangeStmt>(S); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4753 | BlockScopeRAII Scope(Info); | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4754 |  | 
| Richard Smith | 8baa500 | 2018-09-28 18:44:09 +0000 | [diff] [blame] | 4755 | // Evaluate the init-statement if present. | 
|  | 4756 | if (FS->getInit()) { | 
|  | 4757 | EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getInit()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4758 | if (ESR != ESR_Succeeded) { | 
|  | 4759 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4760 | return ESR_Failed; | 
| Richard Smith | 8baa500 | 2018-09-28 18:44:09 +0000 | [diff] [blame] | 4761 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4762 | } | 
| Richard Smith | 8baa500 | 2018-09-28 18:44:09 +0000 | [diff] [blame] | 4763 | } | 
|  | 4764 |  | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4765 | // Initialize the __range variable. | 
|  | 4766 | EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getRangeStmt()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4767 | if (ESR != ESR_Succeeded) { | 
|  | 4768 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4769 | return ESR_Failed; | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4770 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4771 | } | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4772 |  | 
|  | 4773 | // Create the __begin and __end iterators. | 
| Richard Smith | 01694c3 | 2016-03-20 10:33:40 +0000 | [diff] [blame] | 4774 | ESR = EvaluateStmt(Result, Info, FS->getBeginStmt()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4775 | if (ESR != ESR_Succeeded) { | 
|  | 4776 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4777 | return ESR_Failed; | 
| Richard Smith | 01694c3 | 2016-03-20 10:33:40 +0000 | [diff] [blame] | 4778 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4779 | } | 
| Richard Smith | 01694c3 | 2016-03-20 10:33:40 +0000 | [diff] [blame] | 4780 | ESR = EvaluateStmt(Result, Info, FS->getEndStmt()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4781 | if (ESR != ESR_Succeeded) { | 
|  | 4782 | if (ESR != ESR_Failed && !Scope.destroy()) | 
|  | 4783 | return ESR_Failed; | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4784 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4785 | } | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4786 |  | 
|  | 4787 | while (true) { | 
|  | 4788 | // Condition: __begin != __end. | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4789 | { | 
|  | 4790 | bool Continue = true; | 
|  | 4791 | FullExpressionRAII CondExpr(Info); | 
|  | 4792 | if (!EvaluateAsBooleanCondition(FS->getCond(), Continue, Info)) | 
|  | 4793 | return ESR_Failed; | 
|  | 4794 | if (!Continue) | 
|  | 4795 | break; | 
|  | 4796 | } | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4797 |  | 
|  | 4798 | // User's variable declaration, initialized by *__begin. | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 4799 | BlockScopeRAII InnerScope(Info); | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4800 | ESR = EvaluateStmt(Result, Info, FS->getLoopVarStmt()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4801 | if (ESR != ESR_Succeeded) { | 
|  | 4802 | if (ESR != ESR_Failed && (!InnerScope.destroy() || !Scope.destroy())) | 
|  | 4803 | return ESR_Failed; | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4804 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4805 | } | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4806 |  | 
|  | 4807 | // Loop body. | 
|  | 4808 | ESR = EvaluateLoopBody(Result, Info, FS->getBody()); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4809 | if (ESR != ESR_Continue) { | 
|  | 4810 | if (ESR != ESR_Failed && (!InnerScope.destroy() || !Scope.destroy())) | 
|  | 4811 | return ESR_Failed; | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4812 | return ESR; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4813 | } | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4814 |  | 
|  | 4815 | // Increment: ++__begin | 
|  | 4816 | if (!EvaluateIgnoredValue(Info, FS->getInc())) | 
|  | 4817 | return ESR_Failed; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4818 |  | 
|  | 4819 | if (!InnerScope.destroy()) | 
|  | 4820 | return ESR_Failed; | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4821 | } | 
|  | 4822 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 4823 | return Scope.destroy() ? ESR_Succeeded : ESR_Failed; | 
| Richard Smith | 896e0d7 | 2013-05-06 06:51:17 +0000 | [diff] [blame] | 4824 | } | 
|  | 4825 |  | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4826 | case Stmt::SwitchStmtClass: | 
|  | 4827 | return EvaluateSwitch(Result, Info, cast<SwitchStmt>(S)); | 
|  | 4828 |  | 
| Richard Smith | 4e18ca5 | 2013-05-06 05:56:11 +0000 | [diff] [blame] | 4829 | case Stmt::ContinueStmtClass: | 
|  | 4830 | return ESR_Continue; | 
|  | 4831 |  | 
|  | 4832 | case Stmt::BreakStmtClass: | 
|  | 4833 | return ESR_Break; | 
| Richard Smith | 496ddcf | 2013-05-12 17:32:42 +0000 | [diff] [blame] | 4834 |  | 
|  | 4835 | case Stmt::LabelStmtClass: | 
|  | 4836 | return EvaluateStmt(Result, Info, cast<LabelStmt>(S)->getSubStmt(), Case); | 
|  | 4837 |  | 
|  | 4838 | case Stmt::AttributedStmtClass: | 
|  | 4839 | // As a general principle, C++11 attributes can be ignored without | 
|  | 4840 | // any semantic impact. | 
|  | 4841 | return EvaluateStmt(Result, Info, cast<AttributedStmt>(S)->getSubStmt(), | 
|  | 4842 | Case); | 
|  | 4843 |  | 
|  | 4844 | case Stmt::CaseStmtClass: | 
|  | 4845 | case Stmt::DefaultStmtClass: | 
|  | 4846 | return EvaluateStmt(Result, Info, cast<SwitchCase>(S)->getSubStmt(), Case); | 
| Bruno Cardoso Lopes | 5c1399a | 2018-12-10 19:03:12 +0000 | [diff] [blame] | 4847 | case Stmt::CXXTryStmtClass: | 
|  | 4848 | // Evaluate try blocks by evaluating all sub statements. | 
|  | 4849 | return EvaluateStmt(Result, Info, cast<CXXTryStmt>(S)->getTryBlock(), Case); | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 4850 | } | 
|  | 4851 | } | 
|  | 4852 |  | 
| Richard Smith | cc36f69 | 2011-12-22 02:22:31 +0000 | [diff] [blame] | 4853 | /// CheckTrivialDefaultConstructor - Check whether a constructor is a trivial | 
|  | 4854 | /// default constructor. If so, we'll fold it whether or not it's marked as | 
|  | 4855 | /// constexpr. If it is marked as constexpr, we will never implicitly define it, | 
|  | 4856 | /// so we need special handling. | 
|  | 4857 | static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc, | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 4858 | const CXXConstructorDecl *CD, | 
|  | 4859 | bool IsValueInitialization) { | 
| Richard Smith | cc36f69 | 2011-12-22 02:22:31 +0000 | [diff] [blame] | 4860 | if (!CD->isTrivial() || !CD->isDefaultConstructor()) | 
|  | 4861 | return false; | 
|  | 4862 |  | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 4863 | // Value-initialization does not call a trivial default constructor, so such a | 
|  | 4864 | // call is a core constant expression whether or not the constructor is | 
|  | 4865 | // constexpr. | 
|  | 4866 | if (!CD->isConstexpr() && !IsValueInitialization) { | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 4867 | if (Info.getLangOpts().CPlusPlus11) { | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 4868 | // FIXME: If DiagDecl is an implicitly-declared special member function, | 
|  | 4869 | // we should be much more explicit about why it's not constexpr. | 
|  | 4870 | Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1) | 
|  | 4871 | << /*IsConstexpr*/0 << /*IsConstructor*/1 << CD; | 
|  | 4872 | Info.Note(CD->getLocation(), diag::note_declared_at); | 
| Richard Smith | cc36f69 | 2011-12-22 02:22:31 +0000 | [diff] [blame] | 4873 | } else { | 
|  | 4874 | Info.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr); | 
|  | 4875 | } | 
|  | 4876 | } | 
|  | 4877 | return true; | 
|  | 4878 | } | 
|  | 4879 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4880 | /// CheckConstexprFunction - Check that a function can be called in a constant | 
|  | 4881 | /// expression. | 
|  | 4882 | static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, | 
|  | 4883 | const FunctionDecl *Declaration, | 
| Olivier Goffart | 8bc0caa2e | 2016-02-12 12:34:44 +0000 | [diff] [blame] | 4884 | const FunctionDecl *Definition, | 
|  | 4885 | const Stmt *Body) { | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 4886 | // Potential constant expressions can contain calls to declared, but not yet | 
|  | 4887 | // defined, constexpr functions. | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 4888 | if (Info.checkingPotentialConstantExpression() && !Definition && | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 4889 | Declaration->isConstexpr()) | 
|  | 4890 | return false; | 
|  | 4891 |  | 
| James Y Knight | c7d3e60 | 2018-10-05 17:49:48 +0000 | [diff] [blame] | 4892 | // Bail out if the function declaration itself is invalid.  We will | 
|  | 4893 | // have produced a relevant diagnostic while parsing it, so just | 
|  | 4894 | // note the problematic sub-expression. | 
|  | 4895 | if (Declaration->isInvalidDecl()) { | 
|  | 4896 | Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr); | 
| Richard Smith | 0838f3a | 2013-05-14 05:18:44 +0000 | [diff] [blame] | 4897 | return false; | 
| James Y Knight | c7d3e60 | 2018-10-05 17:49:48 +0000 | [diff] [blame] | 4898 | } | 
| Richard Smith | 0838f3a | 2013-05-14 05:18:44 +0000 | [diff] [blame] | 4899 |  | 
| Richard Smith | d9c6b03 | 2019-05-09 19:45:49 +0000 | [diff] [blame] | 4900 | // DR1872: An instantiated virtual constexpr function can't be called in a | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 4901 | // constant expression (prior to C++20). We can still constant-fold such a | 
|  | 4902 | // call. | 
|  | 4903 | if (!Info.Ctx.getLangOpts().CPlusPlus2a && isa<CXXMethodDecl>(Declaration) && | 
|  | 4904 | cast<CXXMethodDecl>(Declaration)->isVirtual()) | 
|  | 4905 | Info.CCEDiag(CallLoc, diag::note_constexpr_virtual_call); | 
|  | 4906 |  | 
|  | 4907 | if (Definition && Definition->isInvalidDecl()) { | 
|  | 4908 | Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr); | 
| Richard Smith | d9c6b03 | 2019-05-09 19:45:49 +0000 | [diff] [blame] | 4909 | return false; | 
|  | 4910 | } | 
|  | 4911 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4912 | // Can we evaluate this function call? | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 4913 | if (Definition && Definition->isConstexpr() && Body) | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4914 | return true; | 
|  | 4915 |  | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 4916 | if (Info.getLangOpts().CPlusPlus11) { | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4917 | const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 4918 |  | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 4919 | // If this function is not constexpr because it is an inherited | 
|  | 4920 | // non-constexpr constructor, diagnose that directly. | 
|  | 4921 | auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl); | 
|  | 4922 | if (CD && CD->isInheritingConstructor()) { | 
|  | 4923 | auto *Inherited = CD->getInheritedConstructor().getConstructor(); | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 4924 | if (!Inherited->isConstexpr()) | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 4925 | DiagDecl = CD = Inherited; | 
|  | 4926 | } | 
|  | 4927 |  | 
|  | 4928 | // FIXME: If DiagDecl is an implicitly-declared special member function | 
|  | 4929 | // or an inheriting constructor, we should be much more explicit about why | 
|  | 4930 | // it's not constexpr. | 
|  | 4931 | if (CD && CD->isInheritingConstructor()) | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4932 | Info.FFDiag(CallLoc, diag::note_constexpr_invalid_inhctor, 1) | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 4933 | << CD->getInheritedConstructor().getConstructor()->getParent(); | 
|  | 4934 | else | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4935 | Info.FFDiag(CallLoc, diag::note_constexpr_invalid_function, 1) | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 4936 | << DiagDecl->isConstexpr() << (bool)CD << DiagDecl; | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4937 | Info.Note(DiagDecl->getLocation(), diag::note_declared_at); | 
|  | 4938 | } else { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 4939 | Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 4940 | } | 
|  | 4941 | return false; | 
|  | 4942 | } | 
|  | 4943 |  | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 4944 | namespace { | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 4945 | struct CheckDynamicTypeHandler { | 
|  | 4946 | AccessKinds AccessKind; | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 4947 | typedef bool result_type; | 
|  | 4948 | bool failed() { return false; } | 
|  | 4949 | bool found(APValue &Subobj, QualType SubobjType) { return true; } | 
|  | 4950 | bool found(APSInt &Value, QualType SubobjType) { return true; } | 
|  | 4951 | bool found(APFloat &Value, QualType SubobjType) { return true; } | 
|  | 4952 | }; | 
|  | 4953 | } // end anonymous namespace | 
|  | 4954 |  | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 4955 | /// Check that we can access the notional vptr of an object / determine its | 
|  | 4956 | /// dynamic type. | 
|  | 4957 | static bool checkDynamicType(EvalInfo &Info, const Expr *E, const LValue &This, | 
|  | 4958 | AccessKinds AK, bool Polymorphic) { | 
| Richard Smith | dab287b | 2019-05-13 07:51:29 +0000 | [diff] [blame] | 4959 | if (This.Designator.Invalid) | 
|  | 4960 | return false; | 
|  | 4961 |  | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 4962 | CompleteObject Obj = findCompleteObject(Info, E, AK, This, QualType()); | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 4963 |  | 
|  | 4964 | if (!Obj) | 
|  | 4965 | return false; | 
|  | 4966 |  | 
|  | 4967 | if (!Obj.Value) { | 
|  | 4968 | // The object is not usable in constant expressions, so we can't inspect | 
|  | 4969 | // its value to see if it's in-lifetime or what the active union members | 
|  | 4970 | // are. We can still check for a one-past-the-end lvalue. | 
|  | 4971 | if (This.Designator.isOnePastTheEnd() || | 
|  | 4972 | This.Designator.isMostDerivedAnUnsizedArray()) { | 
|  | 4973 | Info.FFDiag(E, This.Designator.isOnePastTheEnd() | 
|  | 4974 | ? diag::note_constexpr_access_past_end | 
|  | 4975 | : diag::note_constexpr_access_unsized_array) | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 4976 | << AK; | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 4977 | return false; | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 4978 | } else if (Polymorphic) { | 
|  | 4979 | // Conservatively refuse to perform a polymorphic operation if we would | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 4980 | // not be able to read a notional 'vptr' value. | 
|  | 4981 | APValue Val; | 
|  | 4982 | This.moveInto(Val); | 
|  | 4983 | QualType StarThisType = | 
|  | 4984 | Info.Ctx.getLValueReferenceType(This.Designator.getType(Info.Ctx)); | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 4985 | Info.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type) | 
|  | 4986 | << AK << Val.getAsString(Info.Ctx, StarThisType); | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 4987 | return false; | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 4988 | } | 
|  | 4989 | return true; | 
|  | 4990 | } | 
|  | 4991 |  | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 4992 | CheckDynamicTypeHandler Handler{AK}; | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 4993 | return Obj && findSubobject(Info, E, Obj, This.Designator, Handler); | 
|  | 4994 | } | 
|  | 4995 |  | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 4996 | /// Check that the pointee of the 'this' pointer in a member function call is | 
|  | 4997 | /// either within its lifetime or in its period of construction or destruction. | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 4998 | static bool | 
|  | 4999 | checkNonVirtualMemberCallThisPointer(EvalInfo &Info, const Expr *E, | 
|  | 5000 | const LValue &This, | 
|  | 5001 | const CXXMethodDecl *NamedMember) { | 
|  | 5002 | return checkDynamicType( | 
|  | 5003 | Info, E, This, | 
|  | 5004 | isa<CXXDestructorDecl>(NamedMember) ? AK_Destroy : AK_MemberCall, false); | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 5005 | } | 
|  | 5006 |  | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5007 | struct DynamicType { | 
|  | 5008 | /// The dynamic class type of the object. | 
|  | 5009 | const CXXRecordDecl *Type; | 
|  | 5010 | /// The corresponding path length in the lvalue. | 
|  | 5011 | unsigned PathLength; | 
|  | 5012 | }; | 
|  | 5013 |  | 
|  | 5014 | static const CXXRecordDecl *getBaseClassType(SubobjectDesignator &Designator, | 
|  | 5015 | unsigned PathLength) { | 
|  | 5016 | assert(PathLength >= Designator.MostDerivedPathLength && PathLength <= | 
|  | 5017 | Designator.Entries.size() && "invalid path length"); | 
|  | 5018 | return (PathLength == Designator.MostDerivedPathLength) | 
|  | 5019 | ? Designator.MostDerivedType->getAsCXXRecordDecl() | 
|  | 5020 | : getAsBaseClass(Designator.Entries[PathLength - 1]); | 
|  | 5021 | } | 
|  | 5022 |  | 
|  | 5023 | /// Determine the dynamic type of an object. | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 5024 | static Optional<DynamicType> ComputeDynamicType(EvalInfo &Info, const Expr *E, | 
|  | 5025 | LValue &This, AccessKinds AK) { | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5026 | // If we don't have an lvalue denoting an object of class type, there is no | 
|  | 5027 | // meaningful dynamic type. (We consider objects of non-class type to have no | 
|  | 5028 | // dynamic type.) | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 5029 | if (!checkDynamicType(Info, E, This, AK, true)) | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5030 | return None; | 
|  | 5031 |  | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 5032 | // Refuse to compute a dynamic type in the presence of virtual bases. This | 
|  | 5033 | // shouldn't happen other than in constant-folding situations, since literal | 
|  | 5034 | // types can't have virtual bases. | 
|  | 5035 | // | 
|  | 5036 | // Note that consumers of DynamicType assume that the type has no virtual | 
|  | 5037 | // bases, and will need modifications if this restriction is relaxed. | 
|  | 5038 | const CXXRecordDecl *Class = | 
|  | 5039 | This.Designator.MostDerivedType->getAsCXXRecordDecl(); | 
|  | 5040 | if (!Class || Class->getNumVBases()) { | 
|  | 5041 | Info.FFDiag(E); | 
|  | 5042 | return None; | 
|  | 5043 | } | 
|  | 5044 |  | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5045 | // FIXME: For very deep class hierarchies, it might be beneficial to use a | 
|  | 5046 | // binary search here instead. But the overwhelmingly common case is that | 
|  | 5047 | // we're not in the middle of a constructor, so it probably doesn't matter | 
|  | 5048 | // in practice. | 
|  | 5049 | ArrayRef<APValue::LValuePathEntry> Path = This.Designator.Entries; | 
|  | 5050 | for (unsigned PathLength = This.Designator.MostDerivedPathLength; | 
|  | 5051 | PathLength <= Path.size(); ++PathLength) { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5052 | switch (Info.isEvaluatingCtorDtor(This.getLValueBase(), | 
|  | 5053 | Path.slice(0, PathLength))) { | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5054 | case ConstructionPhase::Bases: | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5055 | case ConstructionPhase::DestroyingBases: | 
|  | 5056 | // We're constructing or destroying a base class. This is not the dynamic | 
|  | 5057 | // type. | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5058 | break; | 
|  | 5059 |  | 
|  | 5060 | case ConstructionPhase::None: | 
|  | 5061 | case ConstructionPhase::AfterBases: | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5062 | case ConstructionPhase::Destroying: | 
|  | 5063 | // We've finished constructing the base classes and not yet started | 
|  | 5064 | // destroying them again, so this is the dynamic type. | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5065 | return DynamicType{getBaseClassType(This.Designator, PathLength), | 
|  | 5066 | PathLength}; | 
|  | 5067 | } | 
|  | 5068 | } | 
|  | 5069 |  | 
|  | 5070 | // CWG issue 1517: we're constructing a base class of the object described by | 
|  | 5071 | // 'This', so that object has not yet begun its period of construction and | 
|  | 5072 | // any polymorphic operation on it results in undefined behavior. | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 5073 | Info.FFDiag(E); | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5074 | return None; | 
|  | 5075 | } | 
|  | 5076 |  | 
|  | 5077 | /// Perform virtual dispatch. | 
|  | 5078 | static const CXXMethodDecl *HandleVirtualDispatch( | 
|  | 5079 | EvalInfo &Info, const Expr *E, LValue &This, const CXXMethodDecl *Found, | 
|  | 5080 | llvm::SmallVectorImpl<QualType> &CovariantAdjustmentPath) { | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 5081 | Optional<DynamicType> DynType = ComputeDynamicType( | 
|  | 5082 | Info, E, This, | 
|  | 5083 | isa<CXXDestructorDecl>(Found) ? AK_Destroy : AK_MemberCall); | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 5084 | if (!DynType) | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5085 | return nullptr; | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5086 |  | 
|  | 5087 | // Find the final overrider. It must be declared in one of the classes on the | 
|  | 5088 | // path from the dynamic type to the static type. | 
|  | 5089 | // FIXME: If we ever allow literal types to have virtual base classes, that | 
|  | 5090 | // won't be true. | 
|  | 5091 | const CXXMethodDecl *Callee = Found; | 
|  | 5092 | unsigned PathLength = DynType->PathLength; | 
|  | 5093 | for (/**/; PathLength <= This.Designator.Entries.size(); ++PathLength) { | 
|  | 5094 | const CXXRecordDecl *Class = getBaseClassType(This.Designator, PathLength); | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5095 | const CXXMethodDecl *Overrider = | 
|  | 5096 | Found->getCorrespondingMethodDeclaredInClass(Class, false); | 
|  | 5097 | if (Overrider) { | 
|  | 5098 | Callee = Overrider; | 
|  | 5099 | break; | 
|  | 5100 | } | 
|  | 5101 | } | 
|  | 5102 |  | 
|  | 5103 | // C++2a [class.abstract]p6: | 
|  | 5104 | //   the effect of making a virtual call to a pure virtual function [...] is | 
|  | 5105 | //   undefined | 
|  | 5106 | if (Callee->isPure()) { | 
|  | 5107 | Info.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << Callee; | 
|  | 5108 | Info.Note(Callee->getLocation(), diag::note_declared_at); | 
|  | 5109 | return nullptr; | 
|  | 5110 | } | 
|  | 5111 |  | 
|  | 5112 | // If necessary, walk the rest of the path to determine the sequence of | 
|  | 5113 | // covariant adjustment steps to apply. | 
|  | 5114 | if (!Info.Ctx.hasSameUnqualifiedType(Callee->getReturnType(), | 
|  | 5115 | Found->getReturnType())) { | 
|  | 5116 | CovariantAdjustmentPath.push_back(Callee->getReturnType()); | 
|  | 5117 | for (unsigned CovariantPathLength = PathLength + 1; | 
|  | 5118 | CovariantPathLength != This.Designator.Entries.size(); | 
|  | 5119 | ++CovariantPathLength) { | 
|  | 5120 | const CXXRecordDecl *NextClass = | 
|  | 5121 | getBaseClassType(This.Designator, CovariantPathLength); | 
|  | 5122 | const CXXMethodDecl *Next = | 
|  | 5123 | Found->getCorrespondingMethodDeclaredInClass(NextClass, false); | 
|  | 5124 | if (Next && !Info.Ctx.hasSameUnqualifiedType( | 
|  | 5125 | Next->getReturnType(), CovariantAdjustmentPath.back())) | 
|  | 5126 | CovariantAdjustmentPath.push_back(Next->getReturnType()); | 
|  | 5127 | } | 
|  | 5128 | if (!Info.Ctx.hasSameUnqualifiedType(Found->getReturnType(), | 
|  | 5129 | CovariantAdjustmentPath.back())) | 
|  | 5130 | CovariantAdjustmentPath.push_back(Found->getReturnType()); | 
|  | 5131 | } | 
|  | 5132 |  | 
|  | 5133 | // Perform 'this' adjustment. | 
|  | 5134 | if (!CastToDerivedClass(Info, E, This, Callee->getParent(), PathLength)) | 
|  | 5135 | return nullptr; | 
|  | 5136 |  | 
|  | 5137 | return Callee; | 
|  | 5138 | } | 
|  | 5139 |  | 
|  | 5140 | /// Perform the adjustment from a value returned by a virtual function to | 
|  | 5141 | /// a value of the statically expected type, which may be a pointer or | 
|  | 5142 | /// reference to a base class of the returned type. | 
|  | 5143 | static bool HandleCovariantReturnAdjustment(EvalInfo &Info, const Expr *E, | 
|  | 5144 | APValue &Result, | 
|  | 5145 | ArrayRef<QualType> Path) { | 
|  | 5146 | assert(Result.isLValue() && | 
|  | 5147 | "unexpected kind of APValue for covariant return"); | 
|  | 5148 | if (Result.isNullPointer()) | 
|  | 5149 | return true; | 
|  | 5150 |  | 
|  | 5151 | LValue LVal; | 
|  | 5152 | LVal.setFrom(Info.Ctx, Result); | 
|  | 5153 |  | 
|  | 5154 | const CXXRecordDecl *OldClass = Path[0]->getPointeeCXXRecordDecl(); | 
|  | 5155 | for (unsigned I = 1; I != Path.size(); ++I) { | 
|  | 5156 | const CXXRecordDecl *NewClass = Path[I]->getPointeeCXXRecordDecl(); | 
|  | 5157 | assert(OldClass && NewClass && "unexpected kind of covariant return"); | 
|  | 5158 | if (OldClass != NewClass && | 
|  | 5159 | !CastToBaseClass(Info, E, LVal, OldClass, NewClass)) | 
|  | 5160 | return false; | 
|  | 5161 | OldClass = NewClass; | 
|  | 5162 | } | 
|  | 5163 |  | 
|  | 5164 | LVal.moveInto(Result); | 
|  | 5165 | return true; | 
|  | 5166 | } | 
|  | 5167 |  | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 5168 | /// Determine whether \p Base, which is known to be a direct base class of | 
|  | 5169 | /// \p Derived, is a public base class. | 
|  | 5170 | static bool isBaseClassPublic(const CXXRecordDecl *Derived, | 
|  | 5171 | const CXXRecordDecl *Base) { | 
|  | 5172 | for (const CXXBaseSpecifier &BaseSpec : Derived->bases()) { | 
|  | 5173 | auto *BaseClass = BaseSpec.getType()->getAsCXXRecordDecl(); | 
|  | 5174 | if (BaseClass && declaresSameEntity(BaseClass, Base)) | 
|  | 5175 | return BaseSpec.getAccessSpecifier() == AS_public; | 
|  | 5176 | } | 
|  | 5177 | llvm_unreachable("Base is not a direct base of Derived"); | 
|  | 5178 | } | 
|  | 5179 |  | 
|  | 5180 | /// Apply the given dynamic cast operation on the provided lvalue. | 
|  | 5181 | /// | 
|  | 5182 | /// This implements the hard case of dynamic_cast, requiring a "runtime check" | 
|  | 5183 | /// to find a suitable target subobject. | 
|  | 5184 | static bool HandleDynamicCast(EvalInfo &Info, const ExplicitCastExpr *E, | 
|  | 5185 | LValue &Ptr) { | 
|  | 5186 | // We can't do anything with a non-symbolic pointer value. | 
|  | 5187 | SubobjectDesignator &D = Ptr.Designator; | 
|  | 5188 | if (D.Invalid) | 
|  | 5189 | return false; | 
|  | 5190 |  | 
|  | 5191 | // C++ [expr.dynamic.cast]p6: | 
|  | 5192 | //   If v is a null pointer value, the result is a null pointer value. | 
|  | 5193 | if (Ptr.isNullPointer() && !E->isGLValue()) | 
|  | 5194 | return true; | 
|  | 5195 |  | 
|  | 5196 | // For all the other cases, we need the pointer to point to an object within | 
|  | 5197 | // its lifetime / period of construction / destruction, and we need to know | 
|  | 5198 | // its dynamic type. | 
|  | 5199 | Optional<DynamicType> DynType = | 
|  | 5200 | ComputeDynamicType(Info, E, Ptr, AK_DynamicCast); | 
|  | 5201 | if (!DynType) | 
|  | 5202 | return false; | 
|  | 5203 |  | 
|  | 5204 | // C++ [expr.dynamic.cast]p7: | 
|  | 5205 | //   If T is "pointer to cv void", then the result is a pointer to the most | 
|  | 5206 | //   derived object | 
|  | 5207 | if (E->getType()->isVoidPointerType()) | 
|  | 5208 | return CastToDerivedClass(Info, E, Ptr, DynType->Type, DynType->PathLength); | 
|  | 5209 |  | 
|  | 5210 | const CXXRecordDecl *C = E->getTypeAsWritten()->getPointeeCXXRecordDecl(); | 
|  | 5211 | assert(C && "dynamic_cast target is not void pointer nor class"); | 
|  | 5212 | CanQualType CQT = Info.Ctx.getCanonicalType(Info.Ctx.getRecordType(C)); | 
|  | 5213 |  | 
|  | 5214 | auto RuntimeCheckFailed = [&] (CXXBasePaths *Paths) { | 
|  | 5215 | // C++ [expr.dynamic.cast]p9: | 
|  | 5216 | if (!E->isGLValue()) { | 
|  | 5217 | //   The value of a failed cast to pointer type is the null pointer value | 
|  | 5218 | //   of the required result type. | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 5219 | Ptr.setNull(Info.Ctx, E->getType()); | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 5220 | return true; | 
|  | 5221 | } | 
|  | 5222 |  | 
|  | 5223 | //   A failed cast to reference type throws [...] std::bad_cast. | 
|  | 5224 | unsigned DiagKind; | 
|  | 5225 | if (!Paths && (declaresSameEntity(DynType->Type, C) || | 
|  | 5226 | DynType->Type->isDerivedFrom(C))) | 
|  | 5227 | DiagKind = 0; | 
|  | 5228 | else if (!Paths || Paths->begin() == Paths->end()) | 
|  | 5229 | DiagKind = 1; | 
|  | 5230 | else if (Paths->isAmbiguous(CQT)) | 
|  | 5231 | DiagKind = 2; | 
|  | 5232 | else { | 
|  | 5233 | assert(Paths->front().Access != AS_public && "why did the cast fail?"); | 
|  | 5234 | DiagKind = 3; | 
|  | 5235 | } | 
|  | 5236 | Info.FFDiag(E, diag::note_constexpr_dynamic_cast_to_reference_failed) | 
|  | 5237 | << DiagKind << Ptr.Designator.getType(Info.Ctx) | 
|  | 5238 | << Info.Ctx.getRecordType(DynType->Type) | 
|  | 5239 | << E->getType().getUnqualifiedType(); | 
|  | 5240 | return false; | 
|  | 5241 | }; | 
|  | 5242 |  | 
|  | 5243 | // Runtime check, phase 1: | 
|  | 5244 | //   Walk from the base subobject towards the derived object looking for the | 
|  | 5245 | //   target type. | 
|  | 5246 | for (int PathLength = Ptr.Designator.Entries.size(); | 
|  | 5247 | PathLength >= (int)DynType->PathLength; --PathLength) { | 
|  | 5248 | const CXXRecordDecl *Class = getBaseClassType(Ptr.Designator, PathLength); | 
|  | 5249 | if (declaresSameEntity(Class, C)) | 
|  | 5250 | return CastToDerivedClass(Info, E, Ptr, Class, PathLength); | 
|  | 5251 | // We can only walk across public inheritance edges. | 
|  | 5252 | if (PathLength > (int)DynType->PathLength && | 
|  | 5253 | !isBaseClassPublic(getBaseClassType(Ptr.Designator, PathLength - 1), | 
|  | 5254 | Class)) | 
|  | 5255 | return RuntimeCheckFailed(nullptr); | 
|  | 5256 | } | 
|  | 5257 |  | 
|  | 5258 | // Runtime check, phase 2: | 
|  | 5259 | //   Search the dynamic type for an unambiguous public base of type C. | 
|  | 5260 | CXXBasePaths Paths(/*FindAmbiguities=*/true, | 
|  | 5261 | /*RecordPaths=*/true, /*DetectVirtual=*/false); | 
|  | 5262 | if (DynType->Type->isDerivedFrom(C, Paths) && !Paths.isAmbiguous(CQT) && | 
|  | 5263 | Paths.front().Access == AS_public) { | 
|  | 5264 | // Downcast to the dynamic type... | 
|  | 5265 | if (!CastToDerivedClass(Info, E, Ptr, DynType->Type, DynType->PathLength)) | 
|  | 5266 | return false; | 
|  | 5267 | // ... then upcast to the chosen base class subobject. | 
|  | 5268 | for (CXXBasePathElement &Elem : Paths.front()) | 
|  | 5269 | if (!HandleLValueBase(Info, E, Ptr, Elem.Class, Elem.Base)) | 
|  | 5270 | return false; | 
|  | 5271 | return true; | 
|  | 5272 | } | 
|  | 5273 |  | 
|  | 5274 | // Otherwise, the runtime check fails. | 
|  | 5275 | return RuntimeCheckFailed(&Paths); | 
|  | 5276 | } | 
|  | 5277 |  | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5278 | namespace { | 
|  | 5279 | struct StartLifetimeOfUnionMemberHandler { | 
|  | 5280 | const FieldDecl *Field; | 
|  | 5281 |  | 
|  | 5282 | static const AccessKinds AccessKind = AK_Assign; | 
|  | 5283 |  | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5284 | typedef bool result_type; | 
|  | 5285 | bool failed() { return false; } | 
|  | 5286 | bool found(APValue &Subobj, QualType SubobjType) { | 
|  | 5287 | // We are supposed to perform no initialization but begin the lifetime of | 
|  | 5288 | // the object. We interpret that as meaning to do what default | 
|  | 5289 | // initialization of the object would do if all constructors involved were | 
|  | 5290 | // trivial: | 
|  | 5291 | //  * All base, non-variant member, and array element subobjects' lifetimes | 
|  | 5292 | //    begin | 
|  | 5293 | //  * No variant members' lifetimes begin | 
|  | 5294 | //  * All scalar subobjects whose lifetimes begin have indeterminate values | 
|  | 5295 | assert(SubobjType->isUnionType()); | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 5296 | if (!declaresSameEntity(Subobj.getUnionField(), Field) || | 
|  | 5297 | !Subobj.getUnionValue().hasValue()) | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5298 | Subobj.setUnion(Field, getDefaultInitValue(Field->getType())); | 
|  | 5299 | return true; | 
|  | 5300 | } | 
|  | 5301 | bool found(APSInt &Value, QualType SubobjType) { | 
|  | 5302 | llvm_unreachable("wrong value kind for union object"); | 
|  | 5303 | } | 
|  | 5304 | bool found(APFloat &Value, QualType SubobjType) { | 
|  | 5305 | llvm_unreachable("wrong value kind for union object"); | 
|  | 5306 | } | 
|  | 5307 | }; | 
|  | 5308 | } // end anonymous namespace | 
|  | 5309 |  | 
|  | 5310 | const AccessKinds StartLifetimeOfUnionMemberHandler::AccessKind; | 
|  | 5311 |  | 
|  | 5312 | /// Handle a builtin simple-assignment or a call to a trivial assignment | 
|  | 5313 | /// operator whose left-hand side might involve a union member access. If it | 
|  | 5314 | /// does, implicitly start the lifetime of any accessed union elements per | 
|  | 5315 | /// C++20 [class.union]5. | 
|  | 5316 | static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr, | 
|  | 5317 | const LValue &LHS) { | 
|  | 5318 | if (LHS.InvalidBase || LHS.Designator.Invalid) | 
|  | 5319 | return false; | 
|  | 5320 |  | 
|  | 5321 | llvm::SmallVector<std::pair<unsigned, const FieldDecl*>, 4> UnionPathLengths; | 
|  | 5322 | // C++ [class.union]p5: | 
|  | 5323 | //   define the set S(E) of subexpressions of E as follows: | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5324 | unsigned PathLength = LHS.Designator.Entries.size(); | 
| Eric Fiselier | ffafdb9 | 2019-05-23 23:34:43 +0000 | [diff] [blame] | 5325 | for (const Expr *E = LHSExpr; E != nullptr;) { | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5326 | //   -- If E is of the form A.B, S(E) contains the elements of S(A)... | 
|  | 5327 | if (auto *ME = dyn_cast<MemberExpr>(E)) { | 
|  | 5328 | auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()); | 
| Richard Smith | 9a84dc0 | 2019-10-01 00:07:14 +0000 | [diff] [blame] | 5329 | // Note that we can't implicitly start the lifetime of a reference, | 
|  | 5330 | // so we don't need to proceed any further if we reach one. | 
|  | 5331 | if (!FD || FD->getType()->isReferenceType()) | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5332 | break; | 
|  | 5333 |  | 
| Richard Smith | faee39b | 2019-10-27 12:26:36 -0700 | [diff] [blame] | 5334 | //    ... and also contains A.B if B names a union member ... | 
|  | 5335 | if (FD->getParent()->isUnion()) { | 
|  | 5336 | //    ... of a non-class, non-array type, or of a class type with a | 
|  | 5337 | //    trivial default constructor that is not deleted, or an array of | 
|  | 5338 | //    such types. | 
|  | 5339 | auto *RD = | 
|  | 5340 | FD->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); | 
|  | 5341 | if (!RD || RD->hasTrivialDefaultConstructor()) | 
|  | 5342 | UnionPathLengths.push_back({PathLength - 1, FD}); | 
|  | 5343 | } | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5344 |  | 
|  | 5345 | E = ME->getBase(); | 
|  | 5346 | --PathLength; | 
|  | 5347 | assert(declaresSameEntity(FD, | 
|  | 5348 | LHS.Designator.Entries[PathLength] | 
|  | 5349 | .getAsBaseOrMember().getPointer())); | 
|  | 5350 |  | 
|  | 5351 | //   -- If E is of the form A[B] and is interpreted as a built-in array | 
|  | 5352 | //      subscripting operator, S(E) is [S(the array operand, if any)]. | 
|  | 5353 | } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) { | 
|  | 5354 | // Step over an ArrayToPointerDecay implicit cast. | 
|  | 5355 | auto *Base = ASE->getBase()->IgnoreImplicit(); | 
|  | 5356 | if (!Base->getType()->isArrayType()) | 
|  | 5357 | break; | 
|  | 5358 |  | 
|  | 5359 | E = Base; | 
|  | 5360 | --PathLength; | 
|  | 5361 |  | 
|  | 5362 | } else if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) { | 
|  | 5363 | // Step over a derived-to-base conversion. | 
| Eric Fiselier | ffafdb9 | 2019-05-23 23:34:43 +0000 | [diff] [blame] | 5364 | E = ICE->getSubExpr(); | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5365 | if (ICE->getCastKind() == CK_NoOp) | 
|  | 5366 | continue; | 
|  | 5367 | if (ICE->getCastKind() != CK_DerivedToBase && | 
|  | 5368 | ICE->getCastKind() != CK_UncheckedDerivedToBase) | 
|  | 5369 | break; | 
| Richard Smith | a481b01 | 2019-05-30 20:45:12 +0000 | [diff] [blame] | 5370 | // Walk path backwards as we walk up from the base to the derived class. | 
|  | 5371 | for (const CXXBaseSpecifier *Elt : llvm::reverse(ICE->path())) { | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5372 | --PathLength; | 
| Dmitri Gribenko | a10fe83 | 2019-05-22 06:57:23 +0000 | [diff] [blame] | 5373 | (void)Elt; | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5374 | assert(declaresSameEntity(Elt->getType()->getAsCXXRecordDecl(), | 
|  | 5375 | LHS.Designator.Entries[PathLength] | 
|  | 5376 | .getAsBaseOrMember().getPointer())); | 
|  | 5377 | } | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5378 |  | 
|  | 5379 | //   -- Otherwise, S(E) is empty. | 
|  | 5380 | } else { | 
|  | 5381 | break; | 
|  | 5382 | } | 
|  | 5383 | } | 
|  | 5384 |  | 
|  | 5385 | // Common case: no unions' lifetimes are started. | 
|  | 5386 | if (UnionPathLengths.empty()) | 
|  | 5387 | return true; | 
|  | 5388 |  | 
|  | 5389 | //   if modification of X [would access an inactive union member], an object | 
|  | 5390 | //   of the type of X is implicitly created | 
|  | 5391 | CompleteObject Obj = | 
|  | 5392 | findCompleteObject(Info, LHSExpr, AK_Assign, LHS, LHSExpr->getType()); | 
|  | 5393 | if (!Obj) | 
|  | 5394 | return false; | 
|  | 5395 | for (std::pair<unsigned, const FieldDecl *> LengthAndField : | 
|  | 5396 | llvm::reverse(UnionPathLengths)) { | 
|  | 5397 | // Form a designator for the union object. | 
|  | 5398 | SubobjectDesignator D = LHS.Designator; | 
|  | 5399 | D.truncate(Info.Ctx, LHS.Base, LengthAndField.first); | 
|  | 5400 |  | 
|  | 5401 | StartLifetimeOfUnionMemberHandler StartLifetime{LengthAndField.second}; | 
|  | 5402 | if (!findSubobject(Info, LHSExpr, Obj, D, StartLifetime)) | 
|  | 5403 | return false; | 
|  | 5404 | } | 
|  | 5405 |  | 
|  | 5406 | return true; | 
|  | 5407 | } | 
|  | 5408 |  | 
| Richard Smith | be6dd81 | 2014-11-19 21:27:17 +0000 | [diff] [blame] | 5409 | /// Determine if a class has any fields that might need to be copied by a | 
|  | 5410 | /// trivial copy or move operation. | 
|  | 5411 | static bool hasFields(const CXXRecordDecl *RD) { | 
|  | 5412 | if (!RD || RD->isEmpty()) | 
|  | 5413 | return false; | 
|  | 5414 | for (auto *FD : RD->fields()) { | 
|  | 5415 | if (FD->isUnnamedBitfield()) | 
|  | 5416 | continue; | 
|  | 5417 | return true; | 
|  | 5418 | } | 
|  | 5419 | for (auto &Base : RD->bases()) | 
|  | 5420 | if (hasFields(Base.getType()->getAsCXXRecordDecl())) | 
|  | 5421 | return true; | 
|  | 5422 | return false; | 
|  | 5423 | } | 
|  | 5424 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5425 | namespace { | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 5426 | typedef SmallVector<APValue, 8> ArgVector; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5427 | } | 
|  | 5428 |  | 
|  | 5429 | /// EvaluateArgs - Evaluate the arguments to a function call. | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 5430 | static bool EvaluateArgs(ArrayRef<const Expr *> Args, ArgVector &ArgValues, | 
|  | 5431 | EvalInfo &Info, const FunctionDecl *Callee) { | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5432 | bool Success = true; | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 5433 | llvm::SmallBitVector ForbiddenNullArgs; | 
|  | 5434 | if (Callee->hasAttr<NonNullAttr>()) { | 
|  | 5435 | ForbiddenNullArgs.resize(Args.size()); | 
|  | 5436 | for (const auto *Attr : Callee->specific_attrs<NonNullAttr>()) { | 
|  | 5437 | if (!Attr->args_size()) { | 
|  | 5438 | ForbiddenNullArgs.set(); | 
|  | 5439 | break; | 
|  | 5440 | } else | 
|  | 5441 | for (auto Idx : Attr->args()) { | 
|  | 5442 | unsigned ASTIdx = Idx.getASTIndex(); | 
|  | 5443 | if (ASTIdx >= Args.size()) | 
|  | 5444 | continue; | 
|  | 5445 | ForbiddenNullArgs[ASTIdx] = 1; | 
|  | 5446 | } | 
|  | 5447 | } | 
|  | 5448 | } | 
| Gauthier Harnisch | 59c6df9 | 2019-10-10 07:13:20 +0000 | [diff] [blame] | 5449 | for (unsigned Idx = 0; Idx < Args.size(); Idx++) { | 
|  | 5450 | if (!Evaluate(ArgValues[Idx], Info, Args[Idx])) { | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5451 | // If we're checking for a potential constant expression, evaluate all | 
|  | 5452 | // initializers even if some of them fail. | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 5453 | if (!Info.noteFailure()) | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5454 | return false; | 
|  | 5455 | Success = false; | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 5456 | } else if (!ForbiddenNullArgs.empty() && | 
| Gauthier Harnisch | 59c6df9 | 2019-10-10 07:13:20 +0000 | [diff] [blame] | 5457 | ForbiddenNullArgs[Idx] && | 
|  | 5458 | ArgValues[Idx].isLValue() && | 
|  | 5459 | ArgValues[Idx].isNullPointer()) { | 
|  | 5460 | Info.CCEDiag(Args[Idx], diag::note_non_null_attribute_failed); | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 5461 | if (!Info.noteFailure()) | 
|  | 5462 | return false; | 
|  | 5463 | Success = false; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5464 | } | 
|  | 5465 | } | 
|  | 5466 | return Success; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5467 | } | 
|  | 5468 |  | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 5469 | /// Evaluate a function call. | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5470 | static bool HandleFunctionCall(SourceLocation CallLoc, | 
|  | 5471 | const FunctionDecl *Callee, const LValue *This, | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 5472 | ArrayRef<const Expr*> Args, const Stmt *Body, | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 5473 | EvalInfo &Info, APValue &Result, | 
|  | 5474 | const LValue *ResultSlot) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5475 | ArgVector ArgValues(Args.size()); | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 5476 | if (!EvaluateArgs(Args, ArgValues, Info, Callee)) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5477 | return false; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 5478 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5479 | if (!Info.CheckCallLimit(CallLoc)) | 
|  | 5480 | return false; | 
|  | 5481 |  | 
|  | 5482 | CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data()); | 
| Richard Smith | 99005e6 | 2013-05-07 03:19:20 +0000 | [diff] [blame] | 5483 |  | 
|  | 5484 | // For a trivial copy or move assignment, perform an APValue copy. This is | 
|  | 5485 | // essential for unions, where the operations performed by the assignment | 
|  | 5486 | // operator cannot be represented as statements. | 
| Richard Smith | be6dd81 | 2014-11-19 21:27:17 +0000 | [diff] [blame] | 5487 | // | 
|  | 5488 | // Skip this for non-union classes with no fields; in that case, the defaulted | 
|  | 5489 | // copy/move does not actually read the object. | 
| Richard Smith | 99005e6 | 2013-05-07 03:19:20 +0000 | [diff] [blame] | 5490 | const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee); | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 5491 | if (MD && MD->isDefaulted() && | 
|  | 5492 | (MD->getParent()->isUnion() || | 
|  | 5493 | (MD->isTrivial() && hasFields(MD->getParent())))) { | 
| Richard Smith | 99005e6 | 2013-05-07 03:19:20 +0000 | [diff] [blame] | 5494 | assert(This && | 
|  | 5495 | (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())); | 
|  | 5496 | LValue RHS; | 
|  | 5497 | RHS.setFrom(Info.Ctx, ArgValues[0]); | 
|  | 5498 | APValue RHSValue; | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 5499 | if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), RHS, | 
|  | 5500 | RHSValue, MD->getParent()->isUnion())) | 
| Richard Smith | 99005e6 | 2013-05-07 03:19:20 +0000 | [diff] [blame] | 5501 | return false; | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 5502 | if (Info.getLangOpts().CPlusPlus2a && MD->isTrivial() && | 
|  | 5503 | !HandleUnionActiveMemberChange(Info, Args[0], *This)) | 
|  | 5504 | return false; | 
| Brian Gesiak | 5488ab4 | 2019-01-11 01:54:53 +0000 | [diff] [blame] | 5505 | if (!handleAssignment(Info, Args[0], *This, MD->getThisType(), | 
| Richard Smith | 99005e6 | 2013-05-07 03:19:20 +0000 | [diff] [blame] | 5506 | RHSValue)) | 
|  | 5507 | return false; | 
|  | 5508 | This->moveInto(Result); | 
|  | 5509 | return true; | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 5510 | } else if (MD && isLambdaCallOperator(MD)) { | 
| Erik Pilkington | 1123291 | 2018-04-05 00:12:05 +0000 | [diff] [blame] | 5511 | // We're in a lambda; determine the lambda capture field maps unless we're | 
|  | 5512 | // just constexpr checking a lambda's call operator. constexpr checking is | 
|  | 5513 | // done before the captures have been added to the closure object (unless | 
|  | 5514 | // we're inferring constexpr-ness), so we don't have access to them in this | 
|  | 5515 | // case. But since we don't need the captures to constexpr check, we can | 
|  | 5516 | // just ignore them. | 
|  | 5517 | if (!Info.checkingPotentialConstantExpression()) | 
|  | 5518 | MD->getParent()->getCaptureFields(Frame.LambdaCaptureFields, | 
|  | 5519 | Frame.LambdaThisCaptureField); | 
| Richard Smith | 99005e6 | 2013-05-07 03:19:20 +0000 | [diff] [blame] | 5520 | } | 
|  | 5521 |  | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 5522 | StmtResult Ret = {Result, ResultSlot}; | 
|  | 5523 | EvalStmtResult ESR = EvaluateStmt(Ret, Info, Body); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 5524 | if (ESR == ESR_Succeeded) { | 
| Alp Toker | 314cc81 | 2014-01-25 16:55:45 +0000 | [diff] [blame] | 5525 | if (Callee->getReturnType()->isVoidType()) | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 5526 | return true; | 
| Stephen Kelly | 1c301dc | 2018-08-09 21:09:38 +0000 | [diff] [blame] | 5527 | Info.FFDiag(Callee->getEndLoc(), diag::note_constexpr_no_return); | 
| Richard Smith | 3da88fa | 2013-04-26 14:36:30 +0000 | [diff] [blame] | 5528 | } | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 5529 | return ESR == ESR_Returned; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 5530 | } | 
|  | 5531 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5532 | /// Evaluate a constructor call. | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 5533 | static bool HandleConstructorCall(const Expr *E, const LValue &This, | 
|  | 5534 | APValue *ArgValues, | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5535 | const CXXConstructorDecl *Definition, | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 5536 | EvalInfo &Info, APValue &Result) { | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 5537 | SourceLocation CallLoc = E->getExprLoc(); | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5538 | if (!Info.CheckCallLimit(CallLoc)) | 
|  | 5539 | return false; | 
|  | 5540 |  | 
| Richard Smith | 3607ffe | 2012-02-13 03:54:03 +0000 | [diff] [blame] | 5541 | const CXXRecordDecl *RD = Definition->getParent(); | 
|  | 5542 | if (RD->getNumVBases()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 5543 | Info.FFDiag(CallLoc, diag::note_constexpr_virtual_base) << RD; | 
| Richard Smith | 3607ffe | 2012-02-13 03:54:03 +0000 | [diff] [blame] | 5544 | return false; | 
|  | 5545 | } | 
|  | 5546 |  | 
| Erik Pilkington | 4292549 | 2017-10-04 00:18:55 +0000 | [diff] [blame] | 5547 | EvalInfo::EvaluatingConstructorRAII EvalObj( | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 5548 | Info, | 
|  | 5549 | ObjectUnderConstruction{This.getLValueBase(), This.Designator.Entries}, | 
|  | 5550 | RD->getNumBases()); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 5551 | CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5552 |  | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 5553 | // FIXME: Creating an APValue just to hold a nonexistent return value is | 
|  | 5554 | // wasteful. | 
|  | 5555 | APValue RetVal; | 
|  | 5556 | StmtResult Ret = {RetVal, nullptr}; | 
|  | 5557 |  | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 5558 | // If it's a delegating constructor, delegate. | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5559 | if (Definition->isDelegatingConstructor()) { | 
|  | 5560 | CXXConstructorDecl::init_const_iterator I = Definition->init_begin(); | 
| Richard Smith | 9ff62af | 2013-11-07 18:45:03 +0000 | [diff] [blame] | 5561 | { | 
|  | 5562 | FullExpressionRAII InitScope(Info); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5563 | if (!EvaluateInPlace(Result, Info, This, (*I)->getInit()) || | 
|  | 5564 | !InitScope.destroy()) | 
| Richard Smith | 9ff62af | 2013-11-07 18:45:03 +0000 | [diff] [blame] | 5565 | return false; | 
|  | 5566 | } | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 5567 | return EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5568 | } | 
|  | 5569 |  | 
| Richard Smith | 1bc5c2c | 2012-01-10 04:32:03 +0000 | [diff] [blame] | 5570 | // For a trivial copy or move constructor, perform an APValue copy. This is | 
| Richard Smith | be6dd81 | 2014-11-19 21:27:17 +0000 | [diff] [blame] | 5571 | // essential for unions (or classes with anonymous union members), where the | 
|  | 5572 | // operations performed by the constructor cannot be represented by | 
|  | 5573 | // ctor-initializers. | 
|  | 5574 | // | 
|  | 5575 | // Skip this for empty non-union classes; we should not perform an | 
|  | 5576 | // lvalue-to-rvalue conversion on them because their copy constructor does not | 
|  | 5577 | // actually read them. | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 5578 | if (Definition->isDefaulted() && Definition->isCopyOrMoveConstructor() && | 
| Richard Smith | be6dd81 | 2014-11-19 21:27:17 +0000 | [diff] [blame] | 5579 | (Definition->getParent()->isUnion() || | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 5580 | (Definition->isTrivial() && hasFields(Definition->getParent())))) { | 
| Richard Smith | 1bc5c2c | 2012-01-10 04:32:03 +0000 | [diff] [blame] | 5581 | LValue RHS; | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 5582 | RHS.setFrom(Info.Ctx, ArgValues[0]); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 5583 | return handleLValueToRValueConversion( | 
|  | 5584 | Info, E, Definition->getParamDecl(0)->getType().getNonReferenceType(), | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 5585 | RHS, Result, Definition->getParent()->isUnion()); | 
| Richard Smith | 1bc5c2c | 2012-01-10 04:32:03 +0000 | [diff] [blame] | 5586 | } | 
|  | 5587 |  | 
|  | 5588 | // Reserve space for the struct members. | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 5589 | if (!RD->isUnion() && !Result.hasValue()) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5590 | Result = APValue(APValue::UninitStruct(), RD->getNumBases(), | 
| Aaron Ballman | 62e47c4 | 2014-03-10 13:43:55 +0000 | [diff] [blame] | 5591 | std::distance(RD->field_begin(), RD->field_end())); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5592 |  | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 5593 | if (RD->isInvalidDecl()) return false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5594 | const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); | 
|  | 5595 |  | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 5596 | // A scope for temporaries lifetime-extended by reference members. | 
|  | 5597 | BlockScopeRAII LifetimeExtendedScope(Info); | 
|  | 5598 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5599 | bool Success = true; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5600 | unsigned BasesSeen = 0; | 
|  | 5601 | #ifndef NDEBUG | 
|  | 5602 | CXXRecordDecl::base_class_const_iterator BaseIt = RD->bases_begin(); | 
|  | 5603 | #endif | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 5604 | CXXRecordDecl::field_iterator FieldIt = RD->field_begin(); | 
|  | 5605 | auto SkipToField = [&](FieldDecl *FD, bool Indirect) { | 
|  | 5606 | // We might be initializing the same field again if this is an indirect | 
|  | 5607 | // field initialization. | 
|  | 5608 | if (FieldIt == RD->field_end() || | 
|  | 5609 | FieldIt->getFieldIndex() > FD->getFieldIndex()) { | 
|  | 5610 | assert(Indirect && "fields out of order?"); | 
|  | 5611 | return; | 
|  | 5612 | } | 
|  | 5613 |  | 
|  | 5614 | // Default-initialize any fields with no explicit initializer. | 
|  | 5615 | for (; !declaresSameEntity(*FieldIt, FD); ++FieldIt) { | 
|  | 5616 | assert(FieldIt != RD->field_end() && "missing field?"); | 
|  | 5617 | if (!FieldIt->isUnnamedBitfield()) | 
|  | 5618 | Result.getStructField(FieldIt->getFieldIndex()) = | 
|  | 5619 | getDefaultInitValue(FieldIt->getType()); | 
|  | 5620 | } | 
|  | 5621 | ++FieldIt; | 
|  | 5622 | }; | 
| Aaron Ballman | 0ad7830 | 2014-03-13 17:34:31 +0000 | [diff] [blame] | 5623 | for (const auto *I : Definition->inits()) { | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5624 | LValue Subobject = This; | 
| Volodymyr Sapsai | e8f1ffb | 2018-02-23 23:59:20 +0000 | [diff] [blame] | 5625 | LValue SubobjectParent = This; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5626 | APValue *Value = &Result; | 
|  | 5627 |  | 
|  | 5628 | // Determine the subobject to initialize. | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 5629 | FieldDecl *FD = nullptr; | 
| Aaron Ballman | 0ad7830 | 2014-03-13 17:34:31 +0000 | [diff] [blame] | 5630 | if (I->isBaseInitializer()) { | 
|  | 5631 | QualType BaseType(I->getBaseClass(), 0); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5632 | #ifndef NDEBUG | 
|  | 5633 | // Non-virtual base classes are initialized in the order in the class | 
| Richard Smith | 3607ffe | 2012-02-13 03:54:03 +0000 | [diff] [blame] | 5634 | // definition. We have already checked for virtual base classes. | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5635 | assert(!BaseIt->isVirtual() && "virtual base for literal type"); | 
|  | 5636 | assert(Info.Ctx.hasSameType(BaseIt->getType(), BaseType) && | 
|  | 5637 | "base class initializers not in expected order"); | 
|  | 5638 | ++BaseIt; | 
|  | 5639 | #endif | 
| Aaron Ballman | 0ad7830 | 2014-03-13 17:34:31 +0000 | [diff] [blame] | 5640 | if (!HandleLValueDirectBase(Info, I->getInit(), Subobject, RD, | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 5641 | BaseType->getAsCXXRecordDecl(), &Layout)) | 
|  | 5642 | return false; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5643 | Value = &Result.getStructBase(BasesSeen++); | 
| Aaron Ballman | 0ad7830 | 2014-03-13 17:34:31 +0000 | [diff] [blame] | 5644 | } else if ((FD = I->getMember())) { | 
|  | 5645 | if (!HandleLValueMember(Info, I->getInit(), Subobject, FD, &Layout)) | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 5646 | return false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5647 | if (RD->isUnion()) { | 
|  | 5648 | Result = APValue(FD); | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5649 | Value = &Result.getUnionValue(); | 
|  | 5650 | } else { | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 5651 | SkipToField(FD, false); | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5652 | Value = &Result.getStructField(FD->getFieldIndex()); | 
|  | 5653 | } | 
| Aaron Ballman | 0ad7830 | 2014-03-13 17:34:31 +0000 | [diff] [blame] | 5654 | } else if (IndirectFieldDecl *IFD = I->getIndirectMember()) { | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 5655 | // Walk the indirect field decl's chain to find the object to initialize, | 
|  | 5656 | // and make sure we've initialized every step along it. | 
| Volodymyr Sapsai | e8f1ffb | 2018-02-23 23:59:20 +0000 | [diff] [blame] | 5657 | auto IndirectFieldChain = IFD->chain(); | 
|  | 5658 | for (auto *C : IndirectFieldChain) { | 
| Aaron Ballman | 1391608 | 2014-03-07 18:11:58 +0000 | [diff] [blame] | 5659 | FD = cast<FieldDecl>(C); | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 5660 | CXXRecordDecl *CD = cast<CXXRecordDecl>(FD->getParent()); | 
|  | 5661 | // Switch the union field if it differs. This happens if we had | 
|  | 5662 | // preceding zero-initialization, and we're now initializing a union | 
|  | 5663 | // subobject other than the first. | 
|  | 5664 | // FIXME: In this case, the values of the other subobjects are | 
|  | 5665 | // specified, since zero-initialization sets all padding bits to zero. | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 5666 | if (!Value->hasValue() || | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 5667 | (Value->isUnion() && Value->getUnionField() != FD)) { | 
|  | 5668 | if (CD->isUnion()) | 
|  | 5669 | *Value = APValue(FD); | 
|  | 5670 | else | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 5671 | // FIXME: This immediately starts the lifetime of all members of an | 
|  | 5672 | // anonymous struct. It would be preferable to strictly start member | 
|  | 5673 | // lifetime in initialization order. | 
|  | 5674 | *Value = getDefaultInitValue(Info.Ctx.getRecordType(CD)); | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 5675 | } | 
| Volodymyr Sapsai | e8f1ffb | 2018-02-23 23:59:20 +0000 | [diff] [blame] | 5676 | // Store Subobject as its parent before updating it for the last element | 
|  | 5677 | // in the chain. | 
|  | 5678 | if (C == IndirectFieldChain.back()) | 
|  | 5679 | SubobjectParent = Subobject; | 
| Aaron Ballman | 0ad7830 | 2014-03-13 17:34:31 +0000 | [diff] [blame] | 5680 | if (!HandleLValueMember(Info, I->getInit(), Subobject, FD)) | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 5681 | return false; | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 5682 | if (CD->isUnion()) | 
|  | 5683 | Value = &Value->getUnionValue(); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 5684 | else { | 
|  | 5685 | if (C == IndirectFieldChain.front() && !RD->isUnion()) | 
|  | 5686 | SkipToField(FD, true); | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 5687 | Value = &Value->getStructField(FD->getFieldIndex()); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 5688 | } | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 5689 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5690 | } else { | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 5691 | llvm_unreachable("unknown base initializer kind"); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5692 | } | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5693 |  | 
| Volodymyr Sapsai | e8f1ffb | 2018-02-23 23:59:20 +0000 | [diff] [blame] | 5694 | // Need to override This for implicit field initializers as in this case | 
|  | 5695 | // This refers to innermost anonymous struct/union containing initializer, | 
|  | 5696 | // not to currently constructed class. | 
|  | 5697 | const Expr *Init = I->getInit(); | 
|  | 5698 | ThisOverrideRAII ThisOverride(*Info.CurrentCall, &SubobjectParent, | 
|  | 5699 | isa<CXXDefaultInitExpr>(Init)); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 5700 | FullExpressionRAII InitScope(Info); | 
| Volodymyr Sapsai | e8f1ffb | 2018-02-23 23:59:20 +0000 | [diff] [blame] | 5701 | if (!EvaluateInPlace(*Value, Info, Subobject, Init) || | 
|  | 5702 | (FD && FD->isBitField() && | 
|  | 5703 | !truncateBitfieldValue(Info, Init, *Value, FD))) { | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5704 | // If we're checking for a potential constant expression, evaluate all | 
|  | 5705 | // initializers even if some of them fail. | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 5706 | if (!Info.noteFailure()) | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 5707 | return false; | 
|  | 5708 | Success = false; | 
|  | 5709 | } | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 5710 |  | 
|  | 5711 | // This is the point at which the dynamic type of the object becomes this | 
|  | 5712 | // class type. | 
|  | 5713 | if (I->isBaseInitializer() && BasesSeen == RD->getNumBases()) | 
|  | 5714 | EvalObj.finishedConstructingBases(); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5715 | } | 
|  | 5716 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 5717 | // Default-initialize any remaining fields. | 
|  | 5718 | if (!RD->isUnion()) { | 
|  | 5719 | for (; FieldIt != RD->field_end(); ++FieldIt) { | 
|  | 5720 | if (!FieldIt->isUnnamedBitfield()) | 
|  | 5721 | Result.getStructField(FieldIt->getFieldIndex()) = | 
|  | 5722 | getDefaultInitValue(FieldIt->getType()); | 
|  | 5723 | } | 
|  | 5724 | } | 
|  | 5725 |  | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 5726 | return Success && | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5727 | EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed && | 
|  | 5728 | LifetimeExtendedScope.destroy(); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 5729 | } | 
|  | 5730 |  | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 5731 | static bool HandleConstructorCall(const Expr *E, const LValue &This, | 
|  | 5732 | ArrayRef<const Expr*> Args, | 
|  | 5733 | const CXXConstructorDecl *Definition, | 
|  | 5734 | EvalInfo &Info, APValue &Result) { | 
|  | 5735 | ArgVector ArgValues(Args.size()); | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 5736 | if (!EvaluateArgs(Args, ArgValues, Info, Definition)) | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 5737 | return false; | 
|  | 5738 |  | 
|  | 5739 | return HandleConstructorCall(E, This, ArgValues.data(), Definition, | 
|  | 5740 | Info, Result); | 
|  | 5741 | } | 
|  | 5742 |  | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 5743 | static bool HandleDestructionImpl(EvalInfo &Info, SourceLocation CallLoc, | 
|  | 5744 | const LValue &This, APValue &Value, | 
|  | 5745 | QualType T) { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 5746 | // Objects can only be destroyed while they're within their lifetimes. | 
|  | 5747 | // FIXME: We have no representation for whether an object of type nullptr_t | 
|  | 5748 | // is in its lifetime; it usually doesn't matter. Perhaps we should model it | 
|  | 5749 | // as indeterminate instead? | 
|  | 5750 | if (Value.isAbsent() && !T->isNullPtrType()) { | 
|  | 5751 | APValue Printable; | 
|  | 5752 | This.moveInto(Printable); | 
|  | 5753 | Info.FFDiag(CallLoc, diag::note_constexpr_destroy_out_of_lifetime) | 
|  | 5754 | << Printable.getAsString(Info.Ctx, Info.Ctx.getLValueReferenceType(T)); | 
|  | 5755 | return false; | 
|  | 5756 | } | 
|  | 5757 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5758 | // Invent an expression for location purposes. | 
|  | 5759 | // FIXME: We shouldn't need to do this. | 
|  | 5760 | OpaqueValueExpr LocE(CallLoc, Info.Ctx.IntTy, VK_RValue); | 
|  | 5761 |  | 
|  | 5762 | // For arrays, destroy elements right-to-left. | 
|  | 5763 | if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(T)) { | 
|  | 5764 | uint64_t Size = CAT->getSize().getZExtValue(); | 
|  | 5765 | QualType ElemT = CAT->getElementType(); | 
|  | 5766 |  | 
|  | 5767 | LValue ElemLV = This; | 
|  | 5768 | ElemLV.addArray(Info, &LocE, CAT); | 
|  | 5769 | if (!HandleLValueArrayAdjustment(Info, &LocE, ElemLV, ElemT, Size)) | 
|  | 5770 | return false; | 
|  | 5771 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 5772 | // Ensure that we have actual array elements available to destroy; the | 
|  | 5773 | // destructors might mutate the value, so we can't run them on the array | 
|  | 5774 | // filler. | 
|  | 5775 | if (Size && Size > Value.getArrayInitializedElts()) | 
|  | 5776 | expandArray(Value, Value.getArraySize() - 1); | 
|  | 5777 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5778 | for (; Size != 0; --Size) { | 
|  | 5779 | APValue &Elem = Value.getArrayInitializedElt(Size - 1); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 5780 | if (!HandleLValueArrayAdjustment(Info, &LocE, ElemLV, ElemT, -1) || | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 5781 | !HandleDestructionImpl(Info, CallLoc, ElemLV, Elem, ElemT)) | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5782 | return false; | 
|  | 5783 | } | 
|  | 5784 |  | 
|  | 5785 | // End the lifetime of this array now. | 
|  | 5786 | Value = APValue(); | 
|  | 5787 | return true; | 
|  | 5788 | } | 
|  | 5789 |  | 
|  | 5790 | const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); | 
|  | 5791 | if (!RD) { | 
|  | 5792 | if (T.isDestructedType()) { | 
|  | 5793 | Info.FFDiag(CallLoc, diag::note_constexpr_unsupported_destruction) << T; | 
|  | 5794 | return false; | 
|  | 5795 | } | 
|  | 5796 |  | 
|  | 5797 | Value = APValue(); | 
|  | 5798 | return true; | 
|  | 5799 | } | 
|  | 5800 |  | 
|  | 5801 | if (RD->getNumVBases()) { | 
|  | 5802 | Info.FFDiag(CallLoc, diag::note_constexpr_virtual_base) << RD; | 
|  | 5803 | return false; | 
|  | 5804 | } | 
|  | 5805 |  | 
|  | 5806 | const CXXDestructorDecl *DD = RD->getDestructor(); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 5807 | if (!DD && !RD->hasTrivialDestructor()) { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5808 | Info.FFDiag(CallLoc); | 
|  | 5809 | return false; | 
|  | 5810 | } | 
|  | 5811 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 5812 | if (!DD || DD->isTrivial() || | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5813 | (RD->isAnonymousStructOrUnion() && RD->isUnion())) { | 
|  | 5814 | // A trivial destructor just ends the lifetime of the object. Check for | 
|  | 5815 | // this case before checking for a body, because we might not bother | 
|  | 5816 | // building a body for a trivial destructor. Note that it doesn't matter | 
|  | 5817 | // whether the destructor is constexpr in this case; all trivial | 
|  | 5818 | // destructors are constexpr. | 
|  | 5819 | // | 
|  | 5820 | // If an anonymous union would be destroyed, some enclosing destructor must | 
|  | 5821 | // have been explicitly defined, and the anonymous union destruction should | 
|  | 5822 | // have no effect. | 
|  | 5823 | Value = APValue(); | 
|  | 5824 | return true; | 
|  | 5825 | } | 
|  | 5826 |  | 
|  | 5827 | if (!Info.CheckCallLimit(CallLoc)) | 
|  | 5828 | return false; | 
|  | 5829 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 5830 | const FunctionDecl *Definition = nullptr; | 
|  | 5831 | const Stmt *Body = DD->getBody(Definition); | 
|  | 5832 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5833 | if (!CheckConstexprFunction(Info, CallLoc, DD, Definition, Body)) | 
|  | 5834 | return false; | 
|  | 5835 |  | 
|  | 5836 | CallStackFrame Frame(Info, CallLoc, Definition, &This, nullptr); | 
|  | 5837 |  | 
|  | 5838 | // We're now in the period of destruction of this object. | 
|  | 5839 | unsigned BasesLeft = RD->getNumBases(); | 
|  | 5840 | EvalInfo::EvaluatingDestructorRAII EvalObj( | 
|  | 5841 | Info, | 
|  | 5842 | ObjectUnderConstruction{This.getLValueBase(), This.Designator.Entries}); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 5843 | if (!EvalObj.DidInsert) { | 
|  | 5844 | // C++2a [class.dtor]p19: | 
|  | 5845 | //   the behavior is undefined if the destructor is invoked for an object | 
|  | 5846 | //   whose lifetime has ended | 
|  | 5847 | // (Note that formally the lifetime ends when the period of destruction | 
|  | 5848 | // begins, even though certain uses of the object remain valid until the | 
|  | 5849 | // period of destruction ends.) | 
|  | 5850 | Info.FFDiag(CallLoc, diag::note_constexpr_double_destroy); | 
|  | 5851 | return false; | 
|  | 5852 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5853 |  | 
|  | 5854 | // FIXME: Creating an APValue just to hold a nonexistent return value is | 
|  | 5855 | // wasteful. | 
|  | 5856 | APValue RetVal; | 
|  | 5857 | StmtResult Ret = {RetVal, nullptr}; | 
|  | 5858 | if (EvaluateStmt(Ret, Info, Definition->getBody()) == ESR_Failed) | 
|  | 5859 | return false; | 
|  | 5860 |  | 
|  | 5861 | // A union destructor does not implicitly destroy its members. | 
|  | 5862 | if (RD->isUnion()) | 
|  | 5863 | return true; | 
|  | 5864 |  | 
|  | 5865 | const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); | 
|  | 5866 |  | 
|  | 5867 | // We don't have a good way to iterate fields in reverse, so collect all the | 
|  | 5868 | // fields first and then walk them backwards. | 
|  | 5869 | SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end()); | 
|  | 5870 | for (const FieldDecl *FD : llvm::reverse(Fields)) { | 
|  | 5871 | if (FD->isUnnamedBitfield()) | 
|  | 5872 | continue; | 
|  | 5873 |  | 
|  | 5874 | LValue Subobject = This; | 
|  | 5875 | if (!HandleLValueMember(Info, &LocE, Subobject, FD, &Layout)) | 
|  | 5876 | return false; | 
|  | 5877 |  | 
|  | 5878 | APValue *SubobjectValue = &Value.getStructField(FD->getFieldIndex()); | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 5879 | if (!HandleDestructionImpl(Info, CallLoc, Subobject, *SubobjectValue, | 
|  | 5880 | FD->getType())) | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5881 | return false; | 
|  | 5882 | } | 
|  | 5883 |  | 
|  | 5884 | if (BasesLeft != 0) | 
|  | 5885 | EvalObj.startedDestroyingBases(); | 
|  | 5886 |  | 
|  | 5887 | // Destroy base classes in reverse order. | 
|  | 5888 | for (const CXXBaseSpecifier &Base : llvm::reverse(RD->bases())) { | 
|  | 5889 | --BasesLeft; | 
|  | 5890 |  | 
|  | 5891 | QualType BaseType = Base.getType(); | 
|  | 5892 | LValue Subobject = This; | 
|  | 5893 | if (!HandleLValueDirectBase(Info, &LocE, Subobject, RD, | 
|  | 5894 | BaseType->getAsCXXRecordDecl(), &Layout)) | 
|  | 5895 | return false; | 
|  | 5896 |  | 
|  | 5897 | APValue *SubobjectValue = &Value.getStructBase(BasesLeft); | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 5898 | if (!HandleDestructionImpl(Info, CallLoc, Subobject, *SubobjectValue, | 
|  | 5899 | BaseType)) | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5900 | return false; | 
|  | 5901 | } | 
|  | 5902 | assert(BasesLeft == 0 && "NumBases was wrong?"); | 
|  | 5903 |  | 
|  | 5904 | // The period of destruction ends now. The object is gone. | 
|  | 5905 | Value = APValue(); | 
|  | 5906 | return true; | 
|  | 5907 | } | 
|  | 5908 |  | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 5909 | namespace { | 
|  | 5910 | struct DestroyObjectHandler { | 
|  | 5911 | EvalInfo &Info; | 
|  | 5912 | const Expr *E; | 
|  | 5913 | const LValue &This; | 
|  | 5914 | const AccessKinds AccessKind; | 
|  | 5915 |  | 
|  | 5916 | typedef bool result_type; | 
|  | 5917 | bool failed() { return false; } | 
|  | 5918 | bool found(APValue &Subobj, QualType SubobjType) { | 
|  | 5919 | return HandleDestructionImpl(Info, E->getExprLoc(), This, Subobj, | 
|  | 5920 | SubobjType); | 
|  | 5921 | } | 
|  | 5922 | bool found(APSInt &Value, QualType SubobjType) { | 
|  | 5923 | Info.FFDiag(E, diag::note_constexpr_destroy_complex_elem); | 
|  | 5924 | return false; | 
|  | 5925 | } | 
|  | 5926 | bool found(APFloat &Value, QualType SubobjType) { | 
|  | 5927 | Info.FFDiag(E, diag::note_constexpr_destroy_complex_elem); | 
|  | 5928 | return false; | 
|  | 5929 | } | 
|  | 5930 | }; | 
|  | 5931 | } | 
|  | 5932 |  | 
|  | 5933 | /// Perform a destructor or pseudo-destructor call on the given object, which | 
|  | 5934 | /// might in general not be a complete object. | 
|  | 5935 | static bool HandleDestruction(EvalInfo &Info, const Expr *E, | 
|  | 5936 | const LValue &This, QualType ThisType) { | 
|  | 5937 | CompleteObject Obj = findCompleteObject(Info, E, AK_Destroy, This, ThisType); | 
|  | 5938 | DestroyObjectHandler Handler = {Info, E, This, AK_Destroy}; | 
|  | 5939 | return Obj && findSubobject(Info, E, Obj, This.Designator, Handler); | 
|  | 5940 | } | 
|  | 5941 |  | 
|  | 5942 | /// Destroy and end the lifetime of the given complete object. | 
|  | 5943 | static bool HandleDestruction(EvalInfo &Info, SourceLocation Loc, | 
|  | 5944 | APValue::LValueBase LVBase, APValue &Value, | 
|  | 5945 | QualType T) { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 5946 | // If we've had an unmodeled side-effect, we can't rely on mutable state | 
|  | 5947 | // (such as the object we're about to destroy) being correct. | 
|  | 5948 | if (Info.EvalStatus.HasSideEffects) | 
|  | 5949 | return false; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5950 |  | 
|  | 5951 | LValue LV; | 
|  | 5952 | LV.set({LVBase}); | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 5953 | return HandleDestructionImpl(Info, Loc, LV, Value, T); | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 5954 | } | 
|  | 5955 |  | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 5956 | /// Perform a call to 'perator new' or to `__builtin_operator_new'. | 
|  | 5957 | static bool HandleOperatorNewCall(EvalInfo &Info, const CallExpr *E, | 
|  | 5958 | LValue &Result) { | 
|  | 5959 | if (Info.checkingPotentialConstantExpression() || | 
|  | 5960 | Info.SpeculativeEvaluationDepth) | 
|  | 5961 | return false; | 
|  | 5962 |  | 
|  | 5963 | // This is permitted only within a call to std::allocator<T>::allocate. | 
|  | 5964 | auto Caller = Info.getStdAllocatorCaller("allocate"); | 
|  | 5965 | if (!Caller) { | 
|  | 5966 | Info.FFDiag(E->getExprLoc(), Info.getLangOpts().CPlusPlus2a | 
|  | 5967 | ? diag::note_constexpr_new_untyped | 
|  | 5968 | : diag::note_constexpr_new); | 
|  | 5969 | return false; | 
|  | 5970 | } | 
|  | 5971 |  | 
|  | 5972 | QualType ElemType = Caller.ElemType; | 
|  | 5973 | if (ElemType->isIncompleteType() || ElemType->isFunctionType()) { | 
|  | 5974 | Info.FFDiag(E->getExprLoc(), | 
|  | 5975 | diag::note_constexpr_new_not_complete_object_type) | 
|  | 5976 | << (ElemType->isIncompleteType() ? 0 : 1) << ElemType; | 
|  | 5977 | return false; | 
|  | 5978 | } | 
|  | 5979 |  | 
|  | 5980 | APSInt ByteSize; | 
|  | 5981 | if (!EvaluateInteger(E->getArg(0), ByteSize, Info)) | 
|  | 5982 | return false; | 
|  | 5983 | bool IsNothrow = false; | 
|  | 5984 | for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I) { | 
|  | 5985 | EvaluateIgnoredValue(Info, E->getArg(I)); | 
|  | 5986 | IsNothrow |= E->getType()->isNothrowT(); | 
|  | 5987 | } | 
|  | 5988 |  | 
|  | 5989 | CharUnits ElemSize; | 
|  | 5990 | if (!HandleSizeof(Info, E->getExprLoc(), ElemType, ElemSize)) | 
|  | 5991 | return false; | 
|  | 5992 | APInt Size, Remainder; | 
|  | 5993 | APInt ElemSizeAP(ByteSize.getBitWidth(), ElemSize.getQuantity()); | 
|  | 5994 | APInt::udivrem(ByteSize, ElemSizeAP, Size, Remainder); | 
|  | 5995 | if (Remainder != 0) { | 
|  | 5996 | // This likely indicates a bug in the implementation of 'std::allocator'. | 
|  | 5997 | Info.FFDiag(E->getExprLoc(), diag::note_constexpr_operator_new_bad_size) | 
|  | 5998 | << ByteSize << APSInt(ElemSizeAP, true) << ElemType; | 
|  | 5999 | return false; | 
|  | 6000 | } | 
|  | 6001 |  | 
|  | 6002 | if (ByteSize.getActiveBits() > ConstantArrayType::getMaxSizeBits(Info.Ctx)) { | 
|  | 6003 | if (IsNothrow) { | 
|  | 6004 | Result.setNull(Info.Ctx, E->getType()); | 
|  | 6005 | return true; | 
|  | 6006 | } | 
|  | 6007 |  | 
|  | 6008 | Info.FFDiag(E, diag::note_constexpr_new_too_large) << APSInt(Size, true); | 
|  | 6009 | return false; | 
|  | 6010 | } | 
|  | 6011 |  | 
| Richard Smith | 772e266 | 2019-10-04 01:25:59 +0000 | [diff] [blame] | 6012 | QualType AllocType = Info.Ctx.getConstantArrayType(ElemType, Size, nullptr, | 
|  | 6013 | ArrayType::Normal, 0); | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 6014 | APValue *Val = Info.createHeapAlloc(E, AllocType, Result); | 
|  | 6015 | *Val = APValue(APValue::UninitArray(), 0, Size.getZExtValue()); | 
|  | 6016 | Result.addArray(Info, E, cast<ConstantArrayType>(AllocType)); | 
|  | 6017 | return true; | 
|  | 6018 | } | 
|  | 6019 |  | 
|  | 6020 | static bool hasVirtualDestructor(QualType T) { | 
|  | 6021 | if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) | 
|  | 6022 | if (CXXDestructorDecl *DD = RD->getDestructor()) | 
|  | 6023 | return DD->isVirtual(); | 
|  | 6024 | return false; | 
|  | 6025 | } | 
|  | 6026 |  | 
| Richard Smith | df3761f | 2019-10-07 03:14:28 +0000 | [diff] [blame] | 6027 | static const FunctionDecl *getVirtualOperatorDelete(QualType T) { | 
|  | 6028 | if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) | 
|  | 6029 | if (CXXDestructorDecl *DD = RD->getDestructor()) | 
|  | 6030 | return DD->isVirtual() ? DD->getOperatorDelete() : nullptr; | 
|  | 6031 | return nullptr; | 
|  | 6032 | } | 
|  | 6033 |  | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 6034 | /// Check that the given object is a suitable pointer to a heap allocation that | 
|  | 6035 | /// still exists and is of the right kind for the purpose of a deletion. | 
|  | 6036 | /// | 
|  | 6037 | /// On success, returns the heap allocation to deallocate. On failure, produces | 
|  | 6038 | /// a diagnostic and returns None. | 
|  | 6039 | static Optional<DynAlloc *> CheckDeleteKind(EvalInfo &Info, const Expr *E, | 
|  | 6040 | const LValue &Pointer, | 
|  | 6041 | DynAlloc::Kind DeallocKind) { | 
|  | 6042 | auto PointerAsString = [&] { | 
|  | 6043 | return Pointer.toString(Info.Ctx, Info.Ctx.VoidPtrTy); | 
|  | 6044 | }; | 
|  | 6045 |  | 
|  | 6046 | DynamicAllocLValue DA = Pointer.Base.dyn_cast<DynamicAllocLValue>(); | 
|  | 6047 | if (!DA) { | 
|  | 6048 | Info.FFDiag(E, diag::note_constexpr_delete_not_heap_alloc) | 
|  | 6049 | << PointerAsString(); | 
|  | 6050 | if (Pointer.Base) | 
|  | 6051 | NoteLValueLocation(Info, Pointer.Base); | 
|  | 6052 | return None; | 
|  | 6053 | } | 
|  | 6054 |  | 
|  | 6055 | Optional<DynAlloc *> Alloc = Info.lookupDynamicAlloc(DA); | 
|  | 6056 | if (!Alloc) { | 
|  | 6057 | Info.FFDiag(E, diag::note_constexpr_double_delete); | 
|  | 6058 | return None; | 
|  | 6059 | } | 
|  | 6060 |  | 
|  | 6061 | QualType AllocType = Pointer.Base.getDynamicAllocType(); | 
|  | 6062 | if (DeallocKind != (*Alloc)->getKind()) { | 
|  | 6063 | Info.FFDiag(E, diag::note_constexpr_new_delete_mismatch) | 
|  | 6064 | << DeallocKind << (*Alloc)->getKind() << AllocType; | 
|  | 6065 | NoteLValueLocation(Info, Pointer.Base); | 
|  | 6066 | return None; | 
|  | 6067 | } | 
|  | 6068 |  | 
|  | 6069 | bool Subobject = false; | 
|  | 6070 | if (DeallocKind == DynAlloc::New) { | 
|  | 6071 | Subobject = Pointer.Designator.MostDerivedPathLength != 0 || | 
|  | 6072 | Pointer.Designator.isOnePastTheEnd(); | 
|  | 6073 | } else { | 
|  | 6074 | Subobject = Pointer.Designator.Entries.size() != 1 || | 
|  | 6075 | Pointer.Designator.Entries[0].getAsArrayIndex() != 0; | 
|  | 6076 | } | 
|  | 6077 | if (Subobject) { | 
|  | 6078 | Info.FFDiag(E, diag::note_constexpr_delete_subobject) | 
|  | 6079 | << PointerAsString() << Pointer.Designator.isOnePastTheEnd(); | 
|  | 6080 | return None; | 
|  | 6081 | } | 
|  | 6082 |  | 
|  | 6083 | return Alloc; | 
|  | 6084 | } | 
|  | 6085 |  | 
|  | 6086 | // Perform a call to 'operator delete' or '__builtin_operator_delete'. | 
|  | 6087 | bool HandleOperatorDeleteCall(EvalInfo &Info, const CallExpr *E) { | 
|  | 6088 | if (Info.checkingPotentialConstantExpression() || | 
|  | 6089 | Info.SpeculativeEvaluationDepth) | 
|  | 6090 | return false; | 
|  | 6091 |  | 
|  | 6092 | // This is permitted only within a call to std::allocator<T>::deallocate. | 
|  | 6093 | if (!Info.getStdAllocatorCaller("deallocate")) { | 
|  | 6094 | Info.FFDiag(E->getExprLoc()); | 
|  | 6095 | return true; | 
|  | 6096 | } | 
|  | 6097 |  | 
|  | 6098 | LValue Pointer; | 
|  | 6099 | if (!EvaluatePointer(E->getArg(0), Pointer, Info)) | 
|  | 6100 | return false; | 
|  | 6101 | for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I) | 
|  | 6102 | EvaluateIgnoredValue(Info, E->getArg(I)); | 
|  | 6103 |  | 
|  | 6104 | if (Pointer.Designator.Invalid) | 
|  | 6105 | return false; | 
|  | 6106 |  | 
|  | 6107 | // Deleting a null pointer has no effect. | 
|  | 6108 | if (Pointer.isNullPointer()) | 
|  | 6109 | return true; | 
|  | 6110 |  | 
|  | 6111 | if (!CheckDeleteKind(Info, E, Pointer, DynAlloc::StdAllocator)) | 
|  | 6112 | return false; | 
|  | 6113 |  | 
|  | 6114 | Info.HeapAllocs.erase(Pointer.Base.get<DynamicAllocLValue>()); | 
|  | 6115 | return true; | 
|  | 6116 | } | 
|  | 6117 |  | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 6118 | //===----------------------------------------------------------------------===// | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6119 | // Generic Evaluation | 
|  | 6120 | //===----------------------------------------------------------------------===// | 
|  | 6121 | namespace { | 
|  | 6122 |  | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 6123 | class BitCastBuffer { | 
|  | 6124 | // FIXME: We're going to need bit-level granularity when we support | 
|  | 6125 | // bit-fields. | 
|  | 6126 | // FIXME: Its possible under the C++ standard for 'char' to not be 8 bits, but | 
|  | 6127 | // we don't support a host or target where that is the case. Still, we should | 
|  | 6128 | // use a more generic type in case we ever do. | 
|  | 6129 | SmallVector<Optional<unsigned char>, 32> Bytes; | 
|  | 6130 |  | 
|  | 6131 | static_assert(std::numeric_limits<unsigned char>::digits >= 8, | 
|  | 6132 | "Need at least 8 bit unsigned char"); | 
|  | 6133 |  | 
|  | 6134 | bool TargetIsLittleEndian; | 
|  | 6135 |  | 
|  | 6136 | public: | 
|  | 6137 | BitCastBuffer(CharUnits Width, bool TargetIsLittleEndian) | 
|  | 6138 | : Bytes(Width.getQuantity()), | 
|  | 6139 | TargetIsLittleEndian(TargetIsLittleEndian) {} | 
|  | 6140 |  | 
|  | 6141 | LLVM_NODISCARD | 
|  | 6142 | bool readObject(CharUnits Offset, CharUnits Width, | 
|  | 6143 | SmallVectorImpl<unsigned char> &Output) const { | 
|  | 6144 | for (CharUnits I = Offset, E = Offset + Width; I != E; ++I) { | 
|  | 6145 | // If a byte of an integer is uninitialized, then the whole integer is | 
|  | 6146 | // uninitalized. | 
|  | 6147 | if (!Bytes[I.getQuantity()]) | 
|  | 6148 | return false; | 
|  | 6149 | Output.push_back(*Bytes[I.getQuantity()]); | 
|  | 6150 | } | 
|  | 6151 | if (llvm::sys::IsLittleEndianHost != TargetIsLittleEndian) | 
|  | 6152 | std::reverse(Output.begin(), Output.end()); | 
|  | 6153 | return true; | 
|  | 6154 | } | 
|  | 6155 |  | 
|  | 6156 | void writeObject(CharUnits Offset, SmallVectorImpl<unsigned char> &Input) { | 
|  | 6157 | if (llvm::sys::IsLittleEndianHost != TargetIsLittleEndian) | 
|  | 6158 | std::reverse(Input.begin(), Input.end()); | 
|  | 6159 |  | 
|  | 6160 | size_t Index = 0; | 
|  | 6161 | for (unsigned char Byte : Input) { | 
|  | 6162 | assert(!Bytes[Offset.getQuantity() + Index] && "overwriting a byte?"); | 
|  | 6163 | Bytes[Offset.getQuantity() + Index] = Byte; | 
|  | 6164 | ++Index; | 
|  | 6165 | } | 
|  | 6166 | } | 
|  | 6167 |  | 
|  | 6168 | size_t size() { return Bytes.size(); } | 
|  | 6169 | }; | 
|  | 6170 |  | 
|  | 6171 | /// Traverse an APValue to produce an BitCastBuffer, emulating how the current | 
|  | 6172 | /// target would represent the value at runtime. | 
|  | 6173 | class APValueToBufferConverter { | 
|  | 6174 | EvalInfo &Info; | 
|  | 6175 | BitCastBuffer Buffer; | 
|  | 6176 | const CastExpr *BCE; | 
|  | 6177 |  | 
|  | 6178 | APValueToBufferConverter(EvalInfo &Info, CharUnits ObjectWidth, | 
|  | 6179 | const CastExpr *BCE) | 
|  | 6180 | : Info(Info), | 
|  | 6181 | Buffer(ObjectWidth, Info.Ctx.getTargetInfo().isLittleEndian()), | 
|  | 6182 | BCE(BCE) {} | 
|  | 6183 |  | 
|  | 6184 | bool visit(const APValue &Val, QualType Ty) { | 
|  | 6185 | return visit(Val, Ty, CharUnits::fromQuantity(0)); | 
|  | 6186 | } | 
|  | 6187 |  | 
|  | 6188 | // Write out Val with type Ty into Buffer starting at Offset. | 
|  | 6189 | bool visit(const APValue &Val, QualType Ty, CharUnits Offset) { | 
|  | 6190 | assert((size_t)Offset.getQuantity() <= Buffer.size()); | 
|  | 6191 |  | 
|  | 6192 | // As a special case, nullptr_t has an indeterminate value. | 
|  | 6193 | if (Ty->isNullPtrType()) | 
|  | 6194 | return true; | 
|  | 6195 |  | 
|  | 6196 | // Dig through Src to find the byte at SrcOffset. | 
|  | 6197 | switch (Val.getKind()) { | 
|  | 6198 | case APValue::Indeterminate: | 
|  | 6199 | case APValue::None: | 
|  | 6200 | return true; | 
|  | 6201 |  | 
|  | 6202 | case APValue::Int: | 
|  | 6203 | return visitInt(Val.getInt(), Ty, Offset); | 
|  | 6204 | case APValue::Float: | 
|  | 6205 | return visitFloat(Val.getFloat(), Ty, Offset); | 
|  | 6206 | case APValue::Array: | 
|  | 6207 | return visitArray(Val, Ty, Offset); | 
|  | 6208 | case APValue::Struct: | 
|  | 6209 | return visitRecord(Val, Ty, Offset); | 
|  | 6210 |  | 
|  | 6211 | case APValue::ComplexInt: | 
|  | 6212 | case APValue::ComplexFloat: | 
|  | 6213 | case APValue::Vector: | 
|  | 6214 | case APValue::FixedPoint: | 
|  | 6215 | // FIXME: We should support these. | 
|  | 6216 |  | 
|  | 6217 | case APValue::Union: | 
|  | 6218 | case APValue::MemberPointer: | 
|  | 6219 | case APValue::AddrLabelDiff: { | 
|  | 6220 | Info.FFDiag(BCE->getBeginLoc(), | 
|  | 6221 | diag::note_constexpr_bit_cast_unsupported_type) | 
|  | 6222 | << Ty; | 
|  | 6223 | return false; | 
|  | 6224 | } | 
|  | 6225 |  | 
|  | 6226 | case APValue::LValue: | 
|  | 6227 | llvm_unreachable("LValue subobject in bit_cast?"); | 
|  | 6228 | } | 
| Simon Pilgrim | 71600be | 2019-07-03 09:54:25 +0000 | [diff] [blame] | 6229 | llvm_unreachable("Unhandled APValue::ValueKind"); | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 6230 | } | 
|  | 6231 |  | 
|  | 6232 | bool visitRecord(const APValue &Val, QualType Ty, CharUnits Offset) { | 
|  | 6233 | const RecordDecl *RD = Ty->getAsRecordDecl(); | 
|  | 6234 | const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); | 
|  | 6235 |  | 
|  | 6236 | // Visit the base classes. | 
|  | 6237 | if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { | 
|  | 6238 | for (size_t I = 0, E = CXXRD->getNumBases(); I != E; ++I) { | 
|  | 6239 | const CXXBaseSpecifier &BS = CXXRD->bases_begin()[I]; | 
|  | 6240 | CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl(); | 
|  | 6241 |  | 
|  | 6242 | if (!visitRecord(Val.getStructBase(I), BS.getType(), | 
|  | 6243 | Layout.getBaseClassOffset(BaseDecl) + Offset)) | 
|  | 6244 | return false; | 
|  | 6245 | } | 
|  | 6246 | } | 
|  | 6247 |  | 
|  | 6248 | // Visit the fields. | 
|  | 6249 | unsigned FieldIdx = 0; | 
|  | 6250 | for (FieldDecl *FD : RD->fields()) { | 
|  | 6251 | if (FD->isBitField()) { | 
|  | 6252 | Info.FFDiag(BCE->getBeginLoc(), | 
|  | 6253 | diag::note_constexpr_bit_cast_unsupported_bitfield); | 
|  | 6254 | return false; | 
|  | 6255 | } | 
|  | 6256 |  | 
|  | 6257 | uint64_t FieldOffsetBits = Layout.getFieldOffset(FieldIdx); | 
|  | 6258 |  | 
|  | 6259 | assert(FieldOffsetBits % Info.Ctx.getCharWidth() == 0 && | 
|  | 6260 | "only bit-fields can have sub-char alignment"); | 
|  | 6261 | CharUnits FieldOffset = | 
|  | 6262 | Info.Ctx.toCharUnitsFromBits(FieldOffsetBits) + Offset; | 
|  | 6263 | QualType FieldTy = FD->getType(); | 
|  | 6264 | if (!visit(Val.getStructField(FieldIdx), FieldTy, FieldOffset)) | 
|  | 6265 | return false; | 
|  | 6266 | ++FieldIdx; | 
|  | 6267 | } | 
|  | 6268 |  | 
|  | 6269 | return true; | 
|  | 6270 | } | 
|  | 6271 |  | 
|  | 6272 | bool visitArray(const APValue &Val, QualType Ty, CharUnits Offset) { | 
|  | 6273 | const auto *CAT = | 
|  | 6274 | dyn_cast_or_null<ConstantArrayType>(Ty->getAsArrayTypeUnsafe()); | 
|  | 6275 | if (!CAT) | 
|  | 6276 | return false; | 
|  | 6277 |  | 
|  | 6278 | CharUnits ElemWidth = Info.Ctx.getTypeSizeInChars(CAT->getElementType()); | 
|  | 6279 | unsigned NumInitializedElts = Val.getArrayInitializedElts(); | 
|  | 6280 | unsigned ArraySize = Val.getArraySize(); | 
|  | 6281 | // First, initialize the initialized elements. | 
|  | 6282 | for (unsigned I = 0; I != NumInitializedElts; ++I) { | 
|  | 6283 | const APValue &SubObj = Val.getArrayInitializedElt(I); | 
|  | 6284 | if (!visit(SubObj, CAT->getElementType(), Offset + I * ElemWidth)) | 
|  | 6285 | return false; | 
|  | 6286 | } | 
|  | 6287 |  | 
|  | 6288 | // Next, initialize the rest of the array using the filler. | 
|  | 6289 | if (Val.hasArrayFiller()) { | 
|  | 6290 | const APValue &Filler = Val.getArrayFiller(); | 
|  | 6291 | for (unsigned I = NumInitializedElts; I != ArraySize; ++I) { | 
|  | 6292 | if (!visit(Filler, CAT->getElementType(), Offset + I * ElemWidth)) | 
|  | 6293 | return false; | 
|  | 6294 | } | 
|  | 6295 | } | 
|  | 6296 |  | 
|  | 6297 | return true; | 
|  | 6298 | } | 
|  | 6299 |  | 
|  | 6300 | bool visitInt(const APSInt &Val, QualType Ty, CharUnits Offset) { | 
|  | 6301 | CharUnits Width = Info.Ctx.getTypeSizeInChars(Ty); | 
|  | 6302 | SmallVector<unsigned char, 8> Bytes(Width.getQuantity()); | 
|  | 6303 | llvm::StoreIntToMemory(Val, &*Bytes.begin(), Width.getQuantity()); | 
|  | 6304 | Buffer.writeObject(Offset, Bytes); | 
|  | 6305 | return true; | 
|  | 6306 | } | 
|  | 6307 |  | 
|  | 6308 | bool visitFloat(const APFloat &Val, QualType Ty, CharUnits Offset) { | 
|  | 6309 | APSInt AsInt(Val.bitcastToAPInt()); | 
|  | 6310 | return visitInt(AsInt, Ty, Offset); | 
|  | 6311 | } | 
|  | 6312 |  | 
|  | 6313 | public: | 
|  | 6314 | static Optional<BitCastBuffer> convert(EvalInfo &Info, const APValue &Src, | 
|  | 6315 | const CastExpr *BCE) { | 
|  | 6316 | CharUnits DstSize = Info.Ctx.getTypeSizeInChars(BCE->getType()); | 
|  | 6317 | APValueToBufferConverter Converter(Info, DstSize, BCE); | 
|  | 6318 | if (!Converter.visit(Src, BCE->getSubExpr()->getType())) | 
|  | 6319 | return None; | 
|  | 6320 | return Converter.Buffer; | 
|  | 6321 | } | 
|  | 6322 | }; | 
|  | 6323 |  | 
|  | 6324 | /// Write an BitCastBuffer into an APValue. | 
|  | 6325 | class BufferToAPValueConverter { | 
|  | 6326 | EvalInfo &Info; | 
|  | 6327 | const BitCastBuffer &Buffer; | 
|  | 6328 | const CastExpr *BCE; | 
|  | 6329 |  | 
|  | 6330 | BufferToAPValueConverter(EvalInfo &Info, const BitCastBuffer &Buffer, | 
|  | 6331 | const CastExpr *BCE) | 
|  | 6332 | : Info(Info), Buffer(Buffer), BCE(BCE) {} | 
|  | 6333 |  | 
|  | 6334 | // Emit an unsupported bit_cast type error. Sema refuses to build a bit_cast | 
|  | 6335 | // with an invalid type, so anything left is a deficiency on our part (FIXME). | 
|  | 6336 | // Ideally this will be unreachable. | 
|  | 6337 | llvm::NoneType unsupportedType(QualType Ty) { | 
|  | 6338 | Info.FFDiag(BCE->getBeginLoc(), | 
|  | 6339 | diag::note_constexpr_bit_cast_unsupported_type) | 
|  | 6340 | << Ty; | 
|  | 6341 | return None; | 
|  | 6342 | } | 
|  | 6343 |  | 
|  | 6344 | Optional<APValue> visit(const BuiltinType *T, CharUnits Offset, | 
|  | 6345 | const EnumType *EnumSugar = nullptr) { | 
|  | 6346 | if (T->isNullPtrType()) { | 
|  | 6347 | uint64_t NullValue = Info.Ctx.getTargetNullPointerValue(QualType(T, 0)); | 
|  | 6348 | return APValue((Expr *)nullptr, | 
|  | 6349 | /*Offset=*/CharUnits::fromQuantity(NullValue), | 
|  | 6350 | APValue::NoLValuePath{}, /*IsNullPtr=*/true); | 
|  | 6351 | } | 
|  | 6352 |  | 
|  | 6353 | CharUnits SizeOf = Info.Ctx.getTypeSizeInChars(T); | 
|  | 6354 | SmallVector<uint8_t, 8> Bytes; | 
|  | 6355 | if (!Buffer.readObject(Offset, SizeOf, Bytes)) { | 
|  | 6356 | // If this is std::byte or unsigned char, then its okay to store an | 
|  | 6357 | // indeterminate value. | 
|  | 6358 | bool IsStdByte = EnumSugar && EnumSugar->isStdByteType(); | 
|  | 6359 | bool IsUChar = | 
|  | 6360 | !EnumSugar && (T->isSpecificBuiltinType(BuiltinType::UChar) || | 
|  | 6361 | T->isSpecificBuiltinType(BuiltinType::Char_U)); | 
|  | 6362 | if (!IsStdByte && !IsUChar) { | 
| Simon Pilgrim | bc7f30e8 | 2019-07-03 12:20:28 +0000 | [diff] [blame] | 6363 | QualType DisplayType(EnumSugar ? (const Type *)EnumSugar : T, 0); | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 6364 | Info.FFDiag(BCE->getExprLoc(), | 
|  | 6365 | diag::note_constexpr_bit_cast_indet_dest) | 
|  | 6366 | << DisplayType << Info.Ctx.getLangOpts().CharIsSigned; | 
|  | 6367 | return None; | 
|  | 6368 | } | 
|  | 6369 |  | 
|  | 6370 | return APValue::IndeterminateValue(); | 
|  | 6371 | } | 
|  | 6372 |  | 
|  | 6373 | APSInt Val(SizeOf.getQuantity() * Info.Ctx.getCharWidth(), true); | 
|  | 6374 | llvm::LoadIntFromMemory(Val, &*Bytes.begin(), Bytes.size()); | 
|  | 6375 |  | 
|  | 6376 | if (T->isIntegralOrEnumerationType()) { | 
|  | 6377 | Val.setIsSigned(T->isSignedIntegerOrEnumerationType()); | 
|  | 6378 | return APValue(Val); | 
|  | 6379 | } | 
|  | 6380 |  | 
|  | 6381 | if (T->isRealFloatingType()) { | 
|  | 6382 | const llvm::fltSemantics &Semantics = | 
|  | 6383 | Info.Ctx.getFloatTypeSemantics(QualType(T, 0)); | 
|  | 6384 | return APValue(APFloat(Semantics, Val)); | 
|  | 6385 | } | 
|  | 6386 |  | 
|  | 6387 | return unsupportedType(QualType(T, 0)); | 
|  | 6388 | } | 
|  | 6389 |  | 
|  | 6390 | Optional<APValue> visit(const RecordType *RTy, CharUnits Offset) { | 
|  | 6391 | const RecordDecl *RD = RTy->getAsRecordDecl(); | 
|  | 6392 | const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); | 
|  | 6393 |  | 
|  | 6394 | unsigned NumBases = 0; | 
|  | 6395 | if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) | 
|  | 6396 | NumBases = CXXRD->getNumBases(); | 
|  | 6397 |  | 
|  | 6398 | APValue ResultVal(APValue::UninitStruct(), NumBases, | 
|  | 6399 | std::distance(RD->field_begin(), RD->field_end())); | 
|  | 6400 |  | 
|  | 6401 | // Visit the base classes. | 
|  | 6402 | if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { | 
|  | 6403 | for (size_t I = 0, E = CXXRD->getNumBases(); I != E; ++I) { | 
|  | 6404 | const CXXBaseSpecifier &BS = CXXRD->bases_begin()[I]; | 
|  | 6405 | CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl(); | 
|  | 6406 | if (BaseDecl->isEmpty() || | 
|  | 6407 | Info.Ctx.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero()) | 
|  | 6408 | continue; | 
|  | 6409 |  | 
|  | 6410 | Optional<APValue> SubObj = visitType( | 
|  | 6411 | BS.getType(), Layout.getBaseClassOffset(BaseDecl) + Offset); | 
|  | 6412 | if (!SubObj) | 
|  | 6413 | return None; | 
|  | 6414 | ResultVal.getStructBase(I) = *SubObj; | 
|  | 6415 | } | 
|  | 6416 | } | 
|  | 6417 |  | 
|  | 6418 | // Visit the fields. | 
|  | 6419 | unsigned FieldIdx = 0; | 
|  | 6420 | for (FieldDecl *FD : RD->fields()) { | 
|  | 6421 | // FIXME: We don't currently support bit-fields. A lot of the logic for | 
|  | 6422 | // this is in CodeGen, so we need to factor it around. | 
|  | 6423 | if (FD->isBitField()) { | 
|  | 6424 | Info.FFDiag(BCE->getBeginLoc(), | 
|  | 6425 | diag::note_constexpr_bit_cast_unsupported_bitfield); | 
|  | 6426 | return None; | 
|  | 6427 | } | 
|  | 6428 |  | 
|  | 6429 | uint64_t FieldOffsetBits = Layout.getFieldOffset(FieldIdx); | 
|  | 6430 | assert(FieldOffsetBits % Info.Ctx.getCharWidth() == 0); | 
|  | 6431 |  | 
|  | 6432 | CharUnits FieldOffset = | 
|  | 6433 | CharUnits::fromQuantity(FieldOffsetBits / Info.Ctx.getCharWidth()) + | 
|  | 6434 | Offset; | 
|  | 6435 | QualType FieldTy = FD->getType(); | 
|  | 6436 | Optional<APValue> SubObj = visitType(FieldTy, FieldOffset); | 
|  | 6437 | if (!SubObj) | 
|  | 6438 | return None; | 
|  | 6439 | ResultVal.getStructField(FieldIdx) = *SubObj; | 
|  | 6440 | ++FieldIdx; | 
|  | 6441 | } | 
|  | 6442 |  | 
|  | 6443 | return ResultVal; | 
|  | 6444 | } | 
|  | 6445 |  | 
|  | 6446 | Optional<APValue> visit(const EnumType *Ty, CharUnits Offset) { | 
|  | 6447 | QualType RepresentationType = Ty->getDecl()->getIntegerType(); | 
|  | 6448 | assert(!RepresentationType.isNull() && | 
|  | 6449 | "enum forward decl should be caught by Sema"); | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 6450 | const auto *AsBuiltin = | 
|  | 6451 | RepresentationType.getCanonicalType()->castAs<BuiltinType>(); | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 6452 | // Recurse into the underlying type. Treat std::byte transparently as | 
|  | 6453 | // unsigned char. | 
|  | 6454 | return visit(AsBuiltin, Offset, /*EnumTy=*/Ty); | 
|  | 6455 | } | 
|  | 6456 |  | 
|  | 6457 | Optional<APValue> visit(const ConstantArrayType *Ty, CharUnits Offset) { | 
|  | 6458 | size_t Size = Ty->getSize().getLimitedValue(); | 
|  | 6459 | CharUnits ElementWidth = Info.Ctx.getTypeSizeInChars(Ty->getElementType()); | 
|  | 6460 |  | 
|  | 6461 | APValue ArrayValue(APValue::UninitArray(), Size, Size); | 
|  | 6462 | for (size_t I = 0; I != Size; ++I) { | 
|  | 6463 | Optional<APValue> ElementValue = | 
|  | 6464 | visitType(Ty->getElementType(), Offset + I * ElementWidth); | 
|  | 6465 | if (!ElementValue) | 
|  | 6466 | return None; | 
|  | 6467 | ArrayValue.getArrayInitializedElt(I) = std::move(*ElementValue); | 
|  | 6468 | } | 
|  | 6469 |  | 
|  | 6470 | return ArrayValue; | 
|  | 6471 | } | 
|  | 6472 |  | 
|  | 6473 | Optional<APValue> visit(const Type *Ty, CharUnits Offset) { | 
|  | 6474 | return unsupportedType(QualType(Ty, 0)); | 
|  | 6475 | } | 
|  | 6476 |  | 
|  | 6477 | Optional<APValue> visitType(QualType Ty, CharUnits Offset) { | 
|  | 6478 | QualType Can = Ty.getCanonicalType(); | 
|  | 6479 |  | 
|  | 6480 | switch (Can->getTypeClass()) { | 
|  | 6481 | #define TYPE(Class, Base)                                                      \ | 
|  | 6482 | case Type::Class:                                                            \ | 
|  | 6483 | return visit(cast<Class##Type>(Can.getTypePtr()), Offset); | 
|  | 6484 | #define ABSTRACT_TYPE(Class, Base) | 
|  | 6485 | #define NON_CANONICAL_TYPE(Class, Base)                                        \ | 
|  | 6486 | case Type::Class:                                                            \ | 
|  | 6487 | llvm_unreachable("non-canonical type should be impossible!"); | 
|  | 6488 | #define DEPENDENT_TYPE(Class, Base)                                            \ | 
|  | 6489 | case Type::Class:                                                            \ | 
|  | 6490 | llvm_unreachable(                                                          \ | 
|  | 6491 | "dependent types aren't supported in the constant evaluator!"); | 
|  | 6492 | #define NON_CANONICAL_UNLESS_DEPENDENT(Class, Base)                            \ | 
|  | 6493 | case Type::Class:                                                            \ | 
|  | 6494 | llvm_unreachable("either dependent or not canonical!"); | 
| John McCall | 36b12a8 | 2019-10-02 06:35:23 +0000 | [diff] [blame] | 6495 | #include "clang/AST/TypeNodes.inc" | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 6496 | } | 
| Simon Pilgrim | 71600be | 2019-07-03 09:54:25 +0000 | [diff] [blame] | 6497 | llvm_unreachable("Unhandled Type::TypeClass"); | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 6498 | } | 
|  | 6499 |  | 
|  | 6500 | public: | 
|  | 6501 | // Pull out a full value of type DstType. | 
|  | 6502 | static Optional<APValue> convert(EvalInfo &Info, BitCastBuffer &Buffer, | 
|  | 6503 | const CastExpr *BCE) { | 
|  | 6504 | BufferToAPValueConverter Converter(Info, Buffer, BCE); | 
|  | 6505 | return Converter.visitType(BCE->getType(), CharUnits::fromQuantity(0)); | 
|  | 6506 | } | 
|  | 6507 | }; | 
|  | 6508 |  | 
|  | 6509 | static bool checkBitCastConstexprEligibilityType(SourceLocation Loc, | 
|  | 6510 | QualType Ty, EvalInfo *Info, | 
|  | 6511 | const ASTContext &Ctx, | 
|  | 6512 | bool CheckingDest) { | 
|  | 6513 | Ty = Ty.getCanonicalType(); | 
|  | 6514 |  | 
|  | 6515 | auto diag = [&](int Reason) { | 
|  | 6516 | if (Info) | 
|  | 6517 | Info->FFDiag(Loc, diag::note_constexpr_bit_cast_invalid_type) | 
|  | 6518 | << CheckingDest << (Reason == 4) << Reason; | 
|  | 6519 | return false; | 
|  | 6520 | }; | 
|  | 6521 | auto note = [&](int Construct, QualType NoteTy, SourceLocation NoteLoc) { | 
|  | 6522 | if (Info) | 
|  | 6523 | Info->Note(NoteLoc, diag::note_constexpr_bit_cast_invalid_subtype) | 
|  | 6524 | << NoteTy << Construct << Ty; | 
|  | 6525 | return false; | 
|  | 6526 | }; | 
|  | 6527 |  | 
|  | 6528 | if (Ty->isUnionType()) | 
|  | 6529 | return diag(0); | 
|  | 6530 | if (Ty->isPointerType()) | 
|  | 6531 | return diag(1); | 
|  | 6532 | if (Ty->isMemberPointerType()) | 
|  | 6533 | return diag(2); | 
|  | 6534 | if (Ty.isVolatileQualified()) | 
|  | 6535 | return diag(3); | 
|  | 6536 |  | 
|  | 6537 | if (RecordDecl *Record = Ty->getAsRecordDecl()) { | 
|  | 6538 | if (auto *CXXRD = dyn_cast<CXXRecordDecl>(Record)) { | 
|  | 6539 | for (CXXBaseSpecifier &BS : CXXRD->bases()) | 
|  | 6540 | if (!checkBitCastConstexprEligibilityType(Loc, BS.getType(), Info, Ctx, | 
|  | 6541 | CheckingDest)) | 
|  | 6542 | return note(1, BS.getType(), BS.getBeginLoc()); | 
|  | 6543 | } | 
|  | 6544 | for (FieldDecl *FD : Record->fields()) { | 
|  | 6545 | if (FD->getType()->isReferenceType()) | 
|  | 6546 | return diag(4); | 
|  | 6547 | if (!checkBitCastConstexprEligibilityType(Loc, FD->getType(), Info, Ctx, | 
|  | 6548 | CheckingDest)) | 
|  | 6549 | return note(0, FD->getType(), FD->getBeginLoc()); | 
|  | 6550 | } | 
|  | 6551 | } | 
|  | 6552 |  | 
|  | 6553 | if (Ty->isArrayType() && | 
|  | 6554 | !checkBitCastConstexprEligibilityType(Loc, Ctx.getBaseElementType(Ty), | 
|  | 6555 | Info, Ctx, CheckingDest)) | 
|  | 6556 | return false; | 
|  | 6557 |  | 
|  | 6558 | return true; | 
|  | 6559 | } | 
|  | 6560 |  | 
|  | 6561 | static bool checkBitCastConstexprEligibility(EvalInfo *Info, | 
|  | 6562 | const ASTContext &Ctx, | 
|  | 6563 | const CastExpr *BCE) { | 
|  | 6564 | bool DestOK = checkBitCastConstexprEligibilityType( | 
|  | 6565 | BCE->getBeginLoc(), BCE->getType(), Info, Ctx, true); | 
|  | 6566 | bool SourceOK = DestOK && checkBitCastConstexprEligibilityType( | 
|  | 6567 | BCE->getBeginLoc(), | 
|  | 6568 | BCE->getSubExpr()->getType(), Info, Ctx, false); | 
|  | 6569 | return SourceOK; | 
|  | 6570 | } | 
|  | 6571 |  | 
|  | 6572 | static bool handleLValueToRValueBitCast(EvalInfo &Info, APValue &DestValue, | 
|  | 6573 | APValue &SourceValue, | 
|  | 6574 | const CastExpr *BCE) { | 
|  | 6575 | assert(CHAR_BIT == 8 && Info.Ctx.getTargetInfo().getCharWidth() == 8 && | 
|  | 6576 | "no host or target supports non 8-bit chars"); | 
|  | 6577 | assert(SourceValue.isLValue() && | 
|  | 6578 | "LValueToRValueBitcast requires an lvalue operand!"); | 
|  | 6579 |  | 
|  | 6580 | if (!checkBitCastConstexprEligibility(&Info, Info.Ctx, BCE)) | 
|  | 6581 | return false; | 
|  | 6582 |  | 
|  | 6583 | LValue SourceLValue; | 
|  | 6584 | APValue SourceRValue; | 
|  | 6585 | SourceLValue.setFrom(Info.Ctx, SourceValue); | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 6586 | if (!handleLValueToRValueConversion( | 
|  | 6587 | Info, BCE, BCE->getSubExpr()->getType().withConst(), SourceLValue, | 
|  | 6588 | SourceRValue, /*WantObjectRepresentation=*/true)) | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 6589 | return false; | 
|  | 6590 |  | 
|  | 6591 | // Read out SourceValue into a char buffer. | 
|  | 6592 | Optional<BitCastBuffer> Buffer = | 
|  | 6593 | APValueToBufferConverter::convert(Info, SourceRValue, BCE); | 
|  | 6594 | if (!Buffer) | 
|  | 6595 | return false; | 
|  | 6596 |  | 
|  | 6597 | // Write out the buffer into a new APValue. | 
|  | 6598 | Optional<APValue> MaybeDestValue = | 
|  | 6599 | BufferToAPValueConverter::convert(Info, *Buffer, BCE); | 
|  | 6600 | if (!MaybeDestValue) | 
|  | 6601 | return false; | 
|  | 6602 |  | 
|  | 6603 | DestValue = std::move(*MaybeDestValue); | 
|  | 6604 | return true; | 
|  | 6605 | } | 
|  | 6606 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6607 | template <class Derived> | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6608 | class ExprEvaluatorBase | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6609 | : public ConstStmtVisitor<Derived, bool> { | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6610 | private: | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 6611 | Derived &getDerived() { return static_cast<Derived&>(*this); } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6612 | bool DerivedSuccess(const APValue &V, const Expr *E) { | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 6613 | return getDerived().Success(V, E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6614 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6615 | bool DerivedZeroInitialization(const Expr *E) { | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 6616 | return getDerived().ZeroInitialization(E); | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 6617 | } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6618 |  | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6619 | // Check whether a conditional operator with a non-constant condition is a | 
|  | 6620 | // potential constant expression. If neither arm is a potential constant | 
|  | 6621 | // expression, then the conditional operator is not either. | 
|  | 6622 | template<typename ConditionalOperator> | 
|  | 6623 | void CheckPotentialConstantConditional(const ConditionalOperator *E) { | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 6624 | assert(Info.checkingPotentialConstantExpression()); | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6625 |  | 
|  | 6626 | // Speculatively evaluate both arms. | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 6627 | SmallVector<PartialDiagnosticAt, 8> Diag; | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6628 | { | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6629 | SpeculativeEvaluationRAII Speculate(Info, &Diag); | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6630 | StmtVisitorTy::Visit(E->getFalseExpr()); | 
|  | 6631 | if (Diag.empty()) | 
|  | 6632 | return; | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 6633 | } | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6634 |  | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 6635 | { | 
|  | 6636 | SpeculativeEvaluationRAII Speculate(Info, &Diag); | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6637 | Diag.clear(); | 
|  | 6638 | StmtVisitorTy::Visit(E->getTrueExpr()); | 
|  | 6639 | if (Diag.empty()) | 
|  | 6640 | return; | 
|  | 6641 | } | 
|  | 6642 |  | 
|  | 6643 | Error(E, diag::note_constexpr_conditional_never_const); | 
|  | 6644 | } | 
|  | 6645 |  | 
|  | 6646 |  | 
|  | 6647 | template<typename ConditionalOperator> | 
|  | 6648 | bool HandleConditionalOperator(const ConditionalOperator *E) { | 
|  | 6649 | bool BoolResult; | 
|  | 6650 | if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) { | 
| Nick Lewycky | 20edee6 | 2017-04-27 07:11:09 +0000 | [diff] [blame] | 6651 | if (Info.checkingPotentialConstantExpression() && Info.noteFailure()) { | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6652 | CheckPotentialConstantConditional(E); | 
| Nick Lewycky | 20edee6 | 2017-04-27 07:11:09 +0000 | [diff] [blame] | 6653 | return false; | 
|  | 6654 | } | 
|  | 6655 | if (Info.noteFailure()) { | 
|  | 6656 | StmtVisitorTy::Visit(E->getTrueExpr()); | 
|  | 6657 | StmtVisitorTy::Visit(E->getFalseExpr()); | 
|  | 6658 | } | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6659 | return false; | 
|  | 6660 | } | 
|  | 6661 |  | 
|  | 6662 | Expr *EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); | 
|  | 6663 | return StmtVisitorTy::Visit(EvalExpr); | 
|  | 6664 | } | 
|  | 6665 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6666 | protected: | 
|  | 6667 | EvalInfo &Info; | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6668 | typedef ConstStmtVisitor<Derived, bool> StmtVisitorTy; | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6669 | typedef ExprEvaluatorBase ExprEvaluatorBaseTy; | 
|  | 6670 |  | 
| Richard Smith | 92b1ce0 | 2011-12-12 09:28:41 +0000 | [diff] [blame] | 6671 | OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 6672 | return Info.CCEDiag(E, D); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6673 | } | 
|  | 6674 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6675 | bool ZeroInitialization(const Expr *E) { return Error(E); } | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 6676 |  | 
|  | 6677 | public: | 
|  | 6678 | ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} | 
|  | 6679 |  | 
|  | 6680 | EvalInfo &getEvalInfo() { return Info; } | 
|  | 6681 |  | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6682 | /// Report an evaluation error. This should only be called when an error is | 
|  | 6683 | /// first discovered. When propagating an error, just return false. | 
|  | 6684 | bool Error(const Expr *E, diag::kind D) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 6685 | Info.FFDiag(E, D); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6686 | return false; | 
|  | 6687 | } | 
|  | 6688 | bool Error(const Expr *E) { | 
|  | 6689 | return Error(E, diag::note_invalid_subexpr_in_const_expr); | 
|  | 6690 | } | 
|  | 6691 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6692 | bool VisitStmt(const Stmt *) { | 
| David Blaikie | 83d382b | 2011-09-23 05:06:16 +0000 | [diff] [blame] | 6693 | llvm_unreachable("Expression evaluator should not be called on stmts"); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6694 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6695 | bool VisitExpr(const Expr *E) { | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6696 | return Error(E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6697 | } | 
|  | 6698 |  | 
| Bill Wendling | 8003edc | 2018-11-09 00:41:36 +0000 | [diff] [blame] | 6699 | bool VisitConstantExpr(const ConstantExpr *E) | 
|  | 6700 | { return StmtVisitorTy::Visit(E->getSubExpr()); } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6701 | bool VisitParenExpr(const ParenExpr *E) | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6702 | { return StmtVisitorTy::Visit(E->getSubExpr()); } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6703 | bool VisitUnaryExtension(const UnaryOperator *E) | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6704 | { return StmtVisitorTy::Visit(E->getSubExpr()); } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6705 | bool VisitUnaryPlus(const UnaryOperator *E) | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6706 | { return StmtVisitorTy::Visit(E->getSubExpr()); } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6707 | bool VisitChooseExpr(const ChooseExpr *E) | 
| Eli Friedman | 75807f2 | 2013-07-20 00:40:58 +0000 | [diff] [blame] | 6708 | { return StmtVisitorTy::Visit(E->getChosenSubExpr()); } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6709 | bool VisitGenericSelectionExpr(const GenericSelectionExpr *E) | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6710 | { return StmtVisitorTy::Visit(E->getResultExpr()); } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6711 | bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) | 
| John McCall | 7c454bb | 2011-07-15 05:09:51 +0000 | [diff] [blame] | 6712 | { return StmtVisitorTy::Visit(E->getReplacement()); } | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 6713 | bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { | 
|  | 6714 | TempVersionRAII RAII(*Info.CurrentCall); | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 6715 | SourceLocExprScopeGuard Guard(E, Info.CurrentCall->CurSourceLocExprScope); | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 6716 | return StmtVisitorTy::Visit(E->getExpr()); | 
|  | 6717 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6718 | bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 6719 | TempVersionRAII RAII(*Info.CurrentCall); | 
| Richard Smith | 17e3246 | 2013-09-13 20:51:45 +0000 | [diff] [blame] | 6720 | // The initializer may not have been parsed yet, or might be erroneous. | 
|  | 6721 | if (!E->getExpr()) | 
|  | 6722 | return Error(E); | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 6723 | SourceLocExprScopeGuard Guard(E, Info.CurrentCall->CurSourceLocExprScope); | 
| Richard Smith | 17e3246 | 2013-09-13 20:51:45 +0000 | [diff] [blame] | 6724 | return StmtVisitorTy::Visit(E->getExpr()); | 
|  | 6725 | } | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 6726 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 6727 | bool VisitExprWithCleanups(const ExprWithCleanups *E) { | 
|  | 6728 | FullExpressionRAII Scope(Info); | 
|  | 6729 | return StmtVisitorTy::Visit(E->getSubExpr()) && Scope.destroy(); | 
|  | 6730 | } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6731 |  | 
| Richard Smith | 3b69bcc | 2019-10-01 00:41:16 +0000 | [diff] [blame] | 6732 | // Temporaries are registered when created, so we don't care about | 
|  | 6733 | // CXXBindTemporaryExpr. | 
|  | 6734 | bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E) { | 
|  | 6735 | return StmtVisitorTy::Visit(E->getSubExpr()); | 
|  | 6736 | } | 
|  | 6737 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6738 | bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { | 
| Richard Smith | 6d6ecc3 | 2011-12-12 12:46:16 +0000 | [diff] [blame] | 6739 | CCEDiag(E, diag::note_constexpr_invalid_cast) << 0; | 
|  | 6740 | return static_cast<Derived*>(this)->VisitCastExpr(E); | 
|  | 6741 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6742 | bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 6743 | if (!Info.Ctx.getLangOpts().CPlusPlus2a) | 
|  | 6744 | CCEDiag(E, diag::note_constexpr_invalid_cast) << 1; | 
| Richard Smith | 6d6ecc3 | 2011-12-12 12:46:16 +0000 | [diff] [blame] | 6745 | return static_cast<Derived*>(this)->VisitCastExpr(E); | 
|  | 6746 | } | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 6747 | bool VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E) { | 
|  | 6748 | return static_cast<Derived*>(this)->VisitCastExpr(E); | 
|  | 6749 | } | 
| Richard Smith | 6d6ecc3 | 2011-12-12 12:46:16 +0000 | [diff] [blame] | 6750 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6751 | bool VisitBinaryOperator(const BinaryOperator *E) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6752 | switch (E->getOpcode()) { | 
|  | 6753 | default: | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6754 | return Error(E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6755 |  | 
|  | 6756 | case BO_Comma: | 
|  | 6757 | VisitIgnoredValue(E->getLHS()); | 
|  | 6758 | return StmtVisitorTy::Visit(E->getRHS()); | 
|  | 6759 |  | 
|  | 6760 | case BO_PtrMemD: | 
|  | 6761 | case BO_PtrMemI: { | 
|  | 6762 | LValue Obj; | 
|  | 6763 | if (!HandleMemberPointerAccess(Info, E, Obj)) | 
|  | 6764 | return false; | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 6765 | APValue Result; | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 6766 | if (!handleLValueToRValueConversion(Info, E, E->getType(), Obj, Result)) | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6767 | return false; | 
|  | 6768 | return DerivedSuccess(Result, E); | 
|  | 6769 | } | 
|  | 6770 | } | 
|  | 6771 | } | 
|  | 6772 |  | 
| Richard Smith | 778dc0f | 2019-10-19 00:04:38 +0000 | [diff] [blame] | 6773 | bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E) { | 
|  | 6774 | return StmtVisitorTy::Visit(E->getSemanticForm()); | 
|  | 6775 | } | 
|  | 6776 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6777 | bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { | 
| Richard Smith | 26d4cc1 | 2012-06-26 08:12:11 +0000 | [diff] [blame] | 6778 | // Evaluate and cache the common expression. We treat it as a temporary, | 
|  | 6779 | // even though it's not quite the same thing. | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 6780 | LValue CommonLV; | 
|  | 6781 | if (!Evaluate(Info.CurrentCall->createTemporary( | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 6782 | E->getOpaqueValue(), | 
|  | 6783 | getStorageType(Info.Ctx, E->getOpaqueValue()), false, | 
|  | 6784 | CommonLV), | 
| Richard Smith | 26d4cc1 | 2012-06-26 08:12:11 +0000 | [diff] [blame] | 6785 | Info, E->getCommon())) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6786 | return false; | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6787 |  | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 6788 | return HandleConditionalOperator(E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6789 | } | 
|  | 6790 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6791 | bool VisitConditionalOperator(const ConditionalOperator *E) { | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 6792 | bool IsBcpCall = false; | 
|  | 6793 | // If the condition (ignoring parens) is a __builtin_constant_p call, | 
|  | 6794 | // the result is a constant expression if it can be folded without | 
|  | 6795 | // side-effects. This is an important GNU extension. See GCC PR38377 | 
|  | 6796 | // for discussion. | 
|  | 6797 | if (const CallExpr *CallCE = | 
|  | 6798 | dyn_cast<CallExpr>(E->getCond()->IgnoreParenCasts())) | 
| Alp Toker | a724cff | 2013-12-28 21:59:02 +0000 | [diff] [blame] | 6799 | if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 6800 | IsBcpCall = true; | 
|  | 6801 |  | 
|  | 6802 | // Always assume __builtin_constant_p(...) ? ... : ... is a potential | 
|  | 6803 | // constant expression; we can't check whether it's potentially foldable. | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 6804 | // FIXME: We should instead treat __builtin_constant_p as non-constant if | 
|  | 6805 | // it would return 'false' in this mode. | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 6806 | if (Info.checkingPotentialConstantExpression() && IsBcpCall) | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 6807 | return false; | 
|  | 6808 |  | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 6809 | FoldConstant Fold(Info, IsBcpCall); | 
|  | 6810 | if (!HandleConditionalOperator(E)) { | 
|  | 6811 | Fold.keepDiagnostics(); | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 6812 | return false; | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 6813 | } | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 6814 |  | 
|  | 6815 | return true; | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6816 | } | 
|  | 6817 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6818 | bool VisitOpaqueValueExpr(const OpaqueValueExpr *E) { | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 6819 | if (APValue *Value = Info.CurrentCall->getCurrentTemporary(E)) | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 6820 | return DerivedSuccess(*Value, E); | 
|  | 6821 |  | 
|  | 6822 | const Expr *Source = E->getSourceExpr(); | 
|  | 6823 | if (!Source) | 
|  | 6824 | return Error(E); | 
|  | 6825 | if (Source == E) { // sanity checking. | 
|  | 6826 | assert(0 && "OpaqueValueExpr recursively refers to itself"); | 
|  | 6827 | return Error(E); | 
| Argyrios Kyrtzidis | fac35c0 | 2011-12-09 02:44:48 +0000 | [diff] [blame] | 6828 | } | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 6829 | return StmtVisitorTy::Visit(Source); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 6830 | } | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 6831 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 6832 | bool VisitCallExpr(const CallExpr *E) { | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 6833 | APValue Result; | 
|  | 6834 | if (!handleCallExpr(E, Result, nullptr)) | 
|  | 6835 | return false; | 
|  | 6836 | return DerivedSuccess(Result, E); | 
|  | 6837 | } | 
|  | 6838 |  | 
|  | 6839 | bool handleCallExpr(const CallExpr *E, APValue &Result, | 
| Nick Lewycky | 13073a6 | 2017-06-12 21:15:44 +0000 | [diff] [blame] | 6840 | const LValue *ResultSlot) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6841 | const Expr *Callee = E->getCallee()->IgnoreParens(); | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 6842 | QualType CalleeType = Callee->getType(); | 
|  | 6843 |  | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 6844 | const FunctionDecl *FD = nullptr; | 
|  | 6845 | LValue *This = nullptr, ThisVal; | 
| Craig Topper | 5fc8fc2 | 2014-08-27 06:28:36 +0000 | [diff] [blame] | 6846 | auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6847 | bool HasQualifier = false; | 
| Richard Smith | 656d49d | 2011-11-10 09:31:24 +0000 | [diff] [blame] | 6848 |  | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 6849 | // Extract function decl and 'this' pointer from the callee. | 
|  | 6850 | if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6851 | const CXXMethodDecl *Member = nullptr; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6852 | if (const MemberExpr *ME = dyn_cast<MemberExpr>(Callee)) { | 
|  | 6853 | // Explicit bound member calls, such as x.f() or p->g(); | 
|  | 6854 | if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal)) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6855 | return false; | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6856 | Member = dyn_cast<CXXMethodDecl>(ME->getMemberDecl()); | 
|  | 6857 | if (!Member) | 
|  | 6858 | return Error(Callee); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6859 | This = &ThisVal; | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6860 | HasQualifier = ME->hasQualifier(); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6861 | } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(Callee)) { | 
|  | 6862 | // Indirect bound member calls ('.*' or '->*'). | 
| Richard Smith | 5258202 | 2019-10-03 01:20:27 +0000 | [diff] [blame] | 6863 | const ValueDecl *D = | 
|  | 6864 | HandleMemberPointerAccess(Info, BE, ThisVal, false); | 
|  | 6865 | if (!D) | 
|  | 6866 | return false; | 
|  | 6867 | Member = dyn_cast<CXXMethodDecl>(D); | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6868 | if (!Member) | 
|  | 6869 | return Error(Callee); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6870 | This = &ThisVal; | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 6871 | } else if (const auto *PDE = dyn_cast<CXXPseudoDestructorExpr>(Callee)) { | 
|  | 6872 | if (!Info.getLangOpts().CPlusPlus2a) | 
|  | 6873 | Info.CCEDiag(PDE, diag::note_constexpr_pseudo_destructor); | 
|  | 6874 | // FIXME: If pseudo-destructor calls ever start ending the lifetime of | 
|  | 6875 | // their callee, we should start calling HandleDestruction here. | 
|  | 6876 | // For now, we just evaluate the object argument and discard it. | 
|  | 6877 | return EvaluateObjectArgument(Info, PDE->getBase(), ThisVal); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 6878 | } else | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6879 | return Error(Callee); | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6880 | FD = Member; | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 6881 | } else if (CalleeType->isFunctionPointerType()) { | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 6882 | LValue Call; | 
|  | 6883 | if (!EvaluatePointer(Callee, Call, Info)) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6884 | return false; | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 6885 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 6886 | if (!Call.getLValueOffset().isZero()) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6887 | return Error(Callee); | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 6888 | FD = dyn_cast_or_null<FunctionDecl>( | 
|  | 6889 | Call.getLValueBase().dyn_cast<const ValueDecl*>()); | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 6890 | if (!FD) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6891 | return Error(Callee); | 
| Faisal Vali | d92e749 | 2017-01-08 18:56:11 +0000 | [diff] [blame] | 6892 | // Don't call function pointers which have been cast to some other type. | 
|  | 6893 | // Per DR (no number yet), the caller and callee can differ in noexcept. | 
|  | 6894 | if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec( | 
|  | 6895 | CalleeType->getPointeeType(), FD->getType())) { | 
|  | 6896 | return Error(E); | 
|  | 6897 | } | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 6898 |  | 
|  | 6899 | // Overloaded operator calls to member functions are represented as normal | 
|  | 6900 | // calls with '*this' as the first argument. | 
|  | 6901 | const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); | 
|  | 6902 | if (MD && !MD->isStatic()) { | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6903 | // FIXME: When selecting an implicit conversion for an overloaded | 
|  | 6904 | // operator delete, we sometimes try to evaluate calls to conversion | 
|  | 6905 | // operators without a 'this' parameter! | 
|  | 6906 | if (Args.empty()) | 
|  | 6907 | return Error(E); | 
|  | 6908 |  | 
| Nick Lewycky | 13073a6 | 2017-06-12 21:15:44 +0000 | [diff] [blame] | 6909 | if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 6910 | return false; | 
|  | 6911 | This = &ThisVal; | 
| Nick Lewycky | 13073a6 | 2017-06-12 21:15:44 +0000 | [diff] [blame] | 6912 | Args = Args.slice(1); | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 6913 | } else if (MD && MD->isLambdaStaticInvoker()) { | 
| Faisal Vali | d92e749 | 2017-01-08 18:56:11 +0000 | [diff] [blame] | 6914 | // Map the static invoker for the lambda back to the call operator. | 
|  | 6915 | // Conveniently, we don't have to slice out the 'this' argument (as is | 
|  | 6916 | // being done for the non-static case), since a static member function | 
|  | 6917 | // doesn't have an implicit argument passed in. | 
|  | 6918 | const CXXRecordDecl *ClosureClass = MD->getParent(); | 
|  | 6919 | assert( | 
|  | 6920 | ClosureClass->captures_begin() == ClosureClass->captures_end() && | 
|  | 6921 | "Number of captures must be zero for conversion to function-ptr"); | 
|  | 6922 |  | 
|  | 6923 | const CXXMethodDecl *LambdaCallOp = | 
|  | 6924 | ClosureClass->getLambdaCallOperator(); | 
|  | 6925 |  | 
|  | 6926 | // Set 'FD', the function that will be called below, to the call | 
|  | 6927 | // operator.  If the closure object represents a generic lambda, find | 
|  | 6928 | // the corresponding specialization of the call operator. | 
|  | 6929 |  | 
|  | 6930 | if (ClosureClass->isGenericLambda()) { | 
|  | 6931 | assert(MD->isFunctionTemplateSpecialization() && | 
|  | 6932 | "A generic lambda's static-invoker function must be a " | 
|  | 6933 | "template specialization"); | 
|  | 6934 | const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs(); | 
|  | 6935 | FunctionTemplateDecl *CallOpTemplate = | 
|  | 6936 | LambdaCallOp->getDescribedFunctionTemplate(); | 
|  | 6937 | void *InsertPos = nullptr; | 
|  | 6938 | FunctionDecl *CorrespondingCallOpSpecialization = | 
|  | 6939 | CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos); | 
|  | 6940 | assert(CorrespondingCallOpSpecialization && | 
|  | 6941 | "We must always have a function call operator specialization " | 
|  | 6942 | "that corresponds to our static invoker specialization"); | 
|  | 6943 | FD = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization); | 
|  | 6944 | } else | 
|  | 6945 | FD = LambdaCallOp; | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 6946 | } else if (FD->isReplaceableGlobalAllocationFunction()) { | 
|  | 6947 | if (FD->getDeclName().getCXXOverloadedOperator() == OO_New || | 
|  | 6948 | FD->getDeclName().getCXXOverloadedOperator() == OO_Array_New) { | 
|  | 6949 | LValue Ptr; | 
|  | 6950 | if (!HandleOperatorNewCall(Info, E, Ptr)) | 
|  | 6951 | return false; | 
|  | 6952 | Ptr.moveInto(Result); | 
|  | 6953 | return true; | 
|  | 6954 | } else { | 
|  | 6955 | return HandleOperatorDeleteCall(Info, E); | 
|  | 6956 | } | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 6957 | } | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 6958 | } else | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6959 | return Error(E); | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 6960 |  | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6961 | SmallVector<QualType, 4> CovariantAdjustmentPath; | 
|  | 6962 | if (This) { | 
|  | 6963 | auto *NamedMember = dyn_cast<CXXMethodDecl>(FD); | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 6964 | if (NamedMember && NamedMember->isVirtual() && !HasQualifier) { | 
|  | 6965 | // Perform virtual dispatch, if necessary. | 
|  | 6966 | FD = HandleVirtualDispatch(Info, E, *This, NamedMember, | 
|  | 6967 | CovariantAdjustmentPath); | 
|  | 6968 | if (!FD) | 
|  | 6969 | return false; | 
|  | 6970 | } else { | 
|  | 6971 | // Check that the 'this' pointer points to an object of the right type. | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 6972 | // FIXME: If this is an assignment operator call, we may need to change | 
|  | 6973 | // the active union member before we check this. | 
|  | 6974 | if (!checkNonVirtualMemberCallThisPointer(Info, E, *This, NamedMember)) | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 6975 | return false; | 
|  | 6976 | } | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6977 | } | 
| Richard Smith | 47b3493 | 2012-02-01 02:39:43 +0000 | [diff] [blame] | 6978 |  | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 6979 | // Destructor calls are different enough that they have their own codepath. | 
|  | 6980 | if (auto *DD = dyn_cast<CXXDestructorDecl>(FD)) { | 
|  | 6981 | assert(This && "no 'this' pointer for destructor call"); | 
|  | 6982 | return HandleDestruction(Info, E, *This, | 
|  | 6983 | Info.Ctx.getRecordType(DD->getParent())); | 
|  | 6984 | } | 
|  | 6985 |  | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 6986 | const FunctionDecl *Definition = nullptr; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 6987 | Stmt *Body = FD->getBody(Definition); | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 6988 |  | 
| Nick Lewycky | 13073a6 | 2017-06-12 21:15:44 +0000 | [diff] [blame] | 6989 | if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || | 
|  | 6990 | !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 6991 | Result, ResultSlot)) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 6992 | return false; | 
|  | 6993 |  | 
| Richard Smith | 921f132 | 2019-05-13 23:35:21 +0000 | [diff] [blame] | 6994 | if (!CovariantAdjustmentPath.empty() && | 
|  | 6995 | !HandleCovariantReturnAdjustment(Info, E, Result, | 
|  | 6996 | CovariantAdjustmentPath)) | 
|  | 6997 | return false; | 
|  | 6998 |  | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 6999 | return true; | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 7000 | } | 
|  | 7001 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7002 | bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7003 | return StmtVisitorTy::Visit(E->getInitializer()); | 
|  | 7004 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7005 | bool VisitInitListExpr(const InitListExpr *E) { | 
| Eli Friedman | 90dc175 | 2012-01-03 23:54:05 +0000 | [diff] [blame] | 7006 | if (E->getNumInits() == 0) | 
|  | 7007 | return DerivedZeroInitialization(E); | 
|  | 7008 | if (E->getNumInits() == 1) | 
|  | 7009 | return StmtVisitorTy::Visit(E->getInit(0)); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 7010 | return Error(E); | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 7011 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7012 | bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 7013 | return DerivedZeroInitialization(E); | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 7014 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7015 | bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 7016 | return DerivedZeroInitialization(E); | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 7017 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7018 | bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 7019 | return DerivedZeroInitialization(E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7020 | } | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 7021 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7022 | /// A member expression where the object is a prvalue is itself a prvalue. | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7023 | bool VisitMemberExpr(const MemberExpr *E) { | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 7024 | assert(!Info.Ctx.getLangOpts().CPlusPlus11 && | 
|  | 7025 | "missing temporary materialization conversion"); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7026 | assert(!E->isArrow() && "missing call to bound member function?"); | 
|  | 7027 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 7028 | APValue Val; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7029 | if (!Evaluate(Val, Info, E->getBase())) | 
|  | 7030 | return false; | 
|  | 7031 |  | 
|  | 7032 | QualType BaseTy = E->getBase()->getType(); | 
|  | 7033 |  | 
|  | 7034 | const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 7035 | if (!FD) return Error(E); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7036 | assert(!FD->getType()->isReferenceType() && "prvalue reference?"); | 
| Ted Kremenek | 2883175 | 2012-08-23 20:46:57 +0000 | [diff] [blame] | 7037 | assert(BaseTy->castAs<RecordType>()->getDecl()->getCanonicalDecl() == | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7038 | FD->getParent()->getCanonicalDecl() && "record / field mismatch"); | 
|  | 7039 |  | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 7040 | // Note: there is no lvalue base here. But this case should only ever | 
|  | 7041 | // happen in C or in C++98, where we cannot be evaluating a constexpr | 
|  | 7042 | // constructor, which is the only case the base matters. | 
| Richard Smith | debad64 | 2019-05-12 09:39:08 +0000 | [diff] [blame] | 7043 | CompleteObject Obj(APValue::LValueBase(), &Val, BaseTy); | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 7044 | SubobjectDesignator Designator(BaseTy); | 
|  | 7045 | Designator.addDeclUnchecked(FD); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7046 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7047 | APValue Result; | 
|  | 7048 | return extractSubobject(Info, E, Obj, Designator, Result) && | 
|  | 7049 | DerivedSuccess(Result, E); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7050 | } | 
|  | 7051 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7052 | bool VisitCastExpr(const CastExpr *E) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7053 | switch (E->getCastKind()) { | 
|  | 7054 | default: | 
|  | 7055 | break; | 
|  | 7056 |  | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 7057 | case CK_AtomicToNonAtomic: { | 
|  | 7058 | APValue AtomicVal; | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 7059 | // This does not need to be done in place even for class/array types: | 
|  | 7060 | // atomic-to-non-atomic conversion implies copying the object | 
|  | 7061 | // representation. | 
|  | 7062 | if (!Evaluate(AtomicVal, Info, E->getSubExpr())) | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 7063 | return false; | 
|  | 7064 | return DerivedSuccess(AtomicVal, E); | 
|  | 7065 | } | 
|  | 7066 |  | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7067 | case CK_NoOp: | 
| Richard Smith | 4ef685b | 2012-01-17 21:17:26 +0000 | [diff] [blame] | 7068 | case CK_UserDefinedConversion: | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7069 | return StmtVisitorTy::Visit(E->getSubExpr()); | 
|  | 7070 |  | 
|  | 7071 | case CK_LValueToRValue: { | 
|  | 7072 | LValue LVal; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 7073 | if (!EvaluateLValue(E->getSubExpr(), LVal, Info)) | 
|  | 7074 | return false; | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 7075 | APValue RVal; | 
| Richard Smith | c82fae6 | 2012-02-05 01:23:16 +0000 | [diff] [blame] | 7076 | // Note, we use the subexpression's type in order to retain cv-qualifiers. | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7077 | if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), | 
| Richard Smith | c82fae6 | 2012-02-05 01:23:16 +0000 | [diff] [blame] | 7078 | LVal, RVal)) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 7079 | return false; | 
|  | 7080 | return DerivedSuccess(RVal, E); | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7081 | } | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 7082 | case CK_LValueToRValueBitCast: { | 
|  | 7083 | APValue DestValue, SourceValue; | 
|  | 7084 | if (!Evaluate(SourceValue, Info, E->getSubExpr())) | 
|  | 7085 | return false; | 
|  | 7086 | if (!handleLValueToRValueBitCast(Info, DestValue, SourceValue, E)) | 
|  | 7087 | return false; | 
|  | 7088 | return DerivedSuccess(DestValue, E); | 
|  | 7089 | } | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7090 | } | 
|  | 7091 |  | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 7092 | return Error(E); | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7093 | } | 
|  | 7094 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7095 | bool VisitUnaryPostInc(const UnaryOperator *UO) { | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7096 | return VisitUnaryPostIncDec(UO); | 
|  | 7097 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7098 | bool VisitUnaryPostDec(const UnaryOperator *UO) { | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7099 | return VisitUnaryPostIncDec(UO); | 
|  | 7100 | } | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7101 | bool VisitUnaryPostIncDec(const UnaryOperator *UO) { | 
| Aaron Ballman | dd69ef3 | 2014-08-19 15:55:55 +0000 | [diff] [blame] | 7102 | if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7103 | return Error(UO); | 
|  | 7104 |  | 
|  | 7105 | LValue LVal; | 
|  | 7106 | if (!EvaluateLValue(UO->getSubExpr(), LVal, Info)) | 
|  | 7107 | return false; | 
|  | 7108 | APValue RVal; | 
|  | 7109 | if (!handleIncDec(this->Info, UO, LVal, UO->getSubExpr()->getType(), | 
|  | 7110 | UO->isIncrementOp(), &RVal)) | 
|  | 7111 | return false; | 
|  | 7112 | return DerivedSuccess(RVal, UO); | 
|  | 7113 | } | 
|  | 7114 |  | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7115 | bool VisitStmtExpr(const StmtExpr *E) { | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 7116 | // We will have checked the full-expressions inside the statement expression | 
|  | 7117 | // when they were completed, and don't need to check them again now. | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 7118 | if (Info.checkingForUndefinedBehavior()) | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 7119 | return Error(E); | 
|  | 7120 |  | 
|  | 7121 | const CompoundStmt *CS = E->getSubStmt(); | 
| Jonathan Roelofs | 104cbf9 | 2015-06-01 16:23:08 +0000 | [diff] [blame] | 7122 | if (CS->body_empty()) | 
|  | 7123 | return true; | 
|  | 7124 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 7125 | BlockScopeRAII Scope(Info); | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 7126 | for (CompoundStmt::const_body_iterator BI = CS->body_begin(), | 
|  | 7127 | BE = CS->body_end(); | 
|  | 7128 | /**/; ++BI) { | 
|  | 7129 | if (BI + 1 == BE) { | 
|  | 7130 | const Expr *FinalExpr = dyn_cast<Expr>(*BI); | 
|  | 7131 | if (!FinalExpr) { | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 7132 | Info.FFDiag((*BI)->getBeginLoc(), | 
|  | 7133 | diag::note_constexpr_stmt_expr_unsupported); | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 7134 | return false; | 
|  | 7135 | } | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 7136 | return this->Visit(FinalExpr) && Scope.destroy(); | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 7137 | } | 
|  | 7138 |  | 
|  | 7139 | APValue ReturnValue; | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 7140 | StmtResult Result = { ReturnValue, nullptr }; | 
|  | 7141 | EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI); | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 7142 | if (ESR != ESR_Succeeded) { | 
|  | 7143 | // FIXME: If the statement-expression terminated due to 'return', | 
|  | 7144 | // 'break', or 'continue', it would be nice to propagate that to | 
|  | 7145 | // the outer statement evaluation rather than bailing out. | 
|  | 7146 | if (ESR != ESR_Failed) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 7147 | Info.FFDiag((*BI)->getBeginLoc(), | 
|  | 7148 | diag::note_constexpr_stmt_expr_unsupported); | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 7149 | return false; | 
|  | 7150 | } | 
|  | 7151 | } | 
| Jonathan Roelofs | 104cbf9 | 2015-06-01 16:23:08 +0000 | [diff] [blame] | 7152 |  | 
|  | 7153 | llvm_unreachable("Return from function from the loop above."); | 
| Richard Smith | 51f0317 | 2013-06-20 03:00:05 +0000 | [diff] [blame] | 7154 | } | 
|  | 7155 |  | 
| Richard Smith | 4a67812 | 2011-10-24 18:44:57 +0000 | [diff] [blame] | 7156 | /// Visit a value which is evaluated, but whose value is ignored. | 
|  | 7157 | void VisitIgnoredValue(const Expr *E) { | 
| Richard Smith | d9f663b | 2013-04-22 15:31:51 +0000 | [diff] [blame] | 7158 | EvaluateIgnoredValue(Info, E); | 
| Richard Smith | 4a67812 | 2011-10-24 18:44:57 +0000 | [diff] [blame] | 7159 | } | 
| David Majnemer | e9807b2 | 2016-02-26 04:23:19 +0000 | [diff] [blame] | 7160 |  | 
|  | 7161 | /// Potentially visit a MemberExpr's base expression. | 
|  | 7162 | void VisitIgnoredBaseExpression(const Expr *E) { | 
|  | 7163 | // While MSVC doesn't evaluate the base expression, it does diagnose the | 
|  | 7164 | // presence of side-effecting behavior. | 
|  | 7165 | if (Info.getLangOpts().MSVCCompat && !E->HasSideEffects(Info.Ctx)) | 
|  | 7166 | return; | 
|  | 7167 | VisitIgnoredValue(E); | 
|  | 7168 | } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7169 | }; | 
|  | 7170 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 7171 | } // namespace | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7172 |  | 
|  | 7173 | //===----------------------------------------------------------------------===// | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7174 | // Common base class for lvalue and temporary evaluation. | 
|  | 7175 | //===----------------------------------------------------------------------===// | 
|  | 7176 | namespace { | 
|  | 7177 | template<class Derived> | 
|  | 7178 | class LValueExprEvaluatorBase | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7179 | : public ExprEvaluatorBase<Derived> { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7180 | protected: | 
|  | 7181 | LValue &Result; | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7182 | bool InvalidBaseOK; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7183 | typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy; | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7184 | typedef ExprEvaluatorBase<Derived> ExprEvaluatorBaseTy; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7185 |  | 
|  | 7186 | bool Success(APValue::LValueBase B) { | 
|  | 7187 | Result.set(B); | 
|  | 7188 | return true; | 
|  | 7189 | } | 
|  | 7190 |  | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7191 | bool evaluatePointer(const Expr *E, LValue &Result) { | 
|  | 7192 | return EvaluatePointer(E, Result, this->Info, InvalidBaseOK); | 
|  | 7193 | } | 
|  | 7194 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7195 | public: | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7196 | LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) | 
|  | 7197 | : ExprEvaluatorBaseTy(Info), Result(Result), | 
|  | 7198 | InvalidBaseOK(InvalidBaseOK) {} | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7199 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 7200 | bool Success(const APValue &V, const Expr *E) { | 
|  | 7201 | Result.setFrom(this->Info.Ctx, V); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7202 | return true; | 
|  | 7203 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7204 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7205 | bool VisitMemberExpr(const MemberExpr *E) { | 
|  | 7206 | // Handle non-static data members. | 
|  | 7207 | QualType BaseTy; | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 7208 | bool EvalOK; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7209 | if (E->isArrow()) { | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7210 | EvalOK = evaluatePointer(E->getBase(), Result); | 
| Ted Kremenek | 2883175 | 2012-08-23 20:46:57 +0000 | [diff] [blame] | 7211 | BaseTy = E->getBase()->getType()->castAs<PointerType>()->getPointeeType(); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 7212 | } else if (E->getBase()->isRValue()) { | 
| Richard Smith | d0b111c | 2011-12-19 22:01:37 +0000 | [diff] [blame] | 7213 | assert(E->getBase()->getType()->isRecordType()); | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 7214 | EvalOK = EvaluateTemporary(E->getBase(), Result, this->Info); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 7215 | BaseTy = E->getBase()->getType(); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7216 | } else { | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 7217 | EvalOK = this->Visit(E->getBase()); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7218 | BaseTy = E->getBase()->getType(); | 
|  | 7219 | } | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 7220 | if (!EvalOK) { | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7221 | if (!InvalidBaseOK) | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 7222 | return false; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 7223 | Result.setInvalid(E); | 
|  | 7224 | return true; | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 7225 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7226 |  | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 7227 | const ValueDecl *MD = E->getMemberDecl(); | 
|  | 7228 | if (const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) { | 
| Simon Pilgrim | 1cd399c | 2019-10-03 11:22:48 +0000 | [diff] [blame] | 7229 | assert(BaseTy->castAs<RecordType>()->getDecl()->getCanonicalDecl() == | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 7230 | FD->getParent()->getCanonicalDecl() && "record / field mismatch"); | 
|  | 7231 | (void)BaseTy; | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 7232 | if (!HandleLValueMember(this->Info, E, Result, FD)) | 
|  | 7233 | return false; | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 7234 | } else if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(MD)) { | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 7235 | if (!HandleLValueIndirectMember(this->Info, E, Result, IFD)) | 
|  | 7236 | return false; | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 7237 | } else | 
|  | 7238 | return this->Error(E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7239 |  | 
| Richard Smith | 1b78b3d | 2012-01-25 22:15:11 +0000 | [diff] [blame] | 7240 | if (MD->getType()->isReferenceType()) { | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 7241 | APValue RefValue; | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7242 | if (!handleLValueToRValueConversion(this->Info, E, MD->getType(), Result, | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7243 | RefValue)) | 
|  | 7244 | return false; | 
|  | 7245 | return Success(RefValue, E); | 
|  | 7246 | } | 
|  | 7247 | return true; | 
|  | 7248 | } | 
|  | 7249 |  | 
|  | 7250 | bool VisitBinaryOperator(const BinaryOperator *E) { | 
|  | 7251 | switch (E->getOpcode()) { | 
|  | 7252 | default: | 
|  | 7253 | return ExprEvaluatorBaseTy::VisitBinaryOperator(E); | 
|  | 7254 |  | 
|  | 7255 | case BO_PtrMemD: | 
|  | 7256 | case BO_PtrMemI: | 
|  | 7257 | return HandleMemberPointerAccess(this->Info, E, Result); | 
|  | 7258 | } | 
|  | 7259 | } | 
|  | 7260 |  | 
|  | 7261 | bool VisitCastExpr(const CastExpr *E) { | 
|  | 7262 | switch (E->getCastKind()) { | 
|  | 7263 | default: | 
|  | 7264 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
|  | 7265 |  | 
|  | 7266 | case CK_DerivedToBase: | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7267 | case CK_UncheckedDerivedToBase: | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7268 | if (!this->Visit(E->getSubExpr())) | 
|  | 7269 | return false; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7270 |  | 
|  | 7271 | // Now figure out the necessary offset to add to the base LV to get from | 
|  | 7272 | // the derived class to the base class. | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7273 | return HandleLValueBasePath(this->Info, E, E->getSubExpr()->getType(), | 
|  | 7274 | Result); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7275 | } | 
|  | 7276 | } | 
|  | 7277 | }; | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 7278 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7279 |  | 
|  | 7280 | //===----------------------------------------------------------------------===// | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7281 | // LValue Evaluation | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7282 | // | 
|  | 7283 | // This is used for evaluating lvalues (in C and C++), xvalues (in C++11), | 
|  | 7284 | // function designators (in C), decl references to void objects (in C), and | 
|  | 7285 | // temporaries (if building with -Wno-address-of-temporary). | 
|  | 7286 | // | 
|  | 7287 | // LValue evaluation produces values comprising a base expression of one of the | 
|  | 7288 | // following types: | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 7289 | // - Declarations | 
|  | 7290 | //  * VarDecl | 
|  | 7291 | //  * FunctionDecl | 
|  | 7292 | // - Literals | 
| Richard Smith | b3189a1 | 2016-12-05 07:49:14 +0000 | [diff] [blame] | 7293 | //  * CompoundLiteralExpr in C (and in global scope in C++) | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7294 | //  * StringLiteral | 
|  | 7295 | //  * PredefinedExpr | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7296 | //  * ObjCStringLiteralExpr | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7297 | //  * ObjCEncodeExpr | 
|  | 7298 | //  * AddrLabelExpr | 
|  | 7299 | //  * BlockExpr | 
|  | 7300 | //  * CallExpr for a MakeStringConstant builtin | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 7301 | // - typeid(T) expressions, as TypeInfoLValues | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 7302 | // - Locals and temporaries | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7303 | //  * MaterializeTemporaryExpr | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 7304 | //  * Any Expr, with a CallIndex indicating the function in which the temporary | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7305 | //    was evaluated, for cases where the MaterializeTemporaryExpr is missing | 
|  | 7306 | //    from the AST (FIXME). | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 7307 | //  * A MaterializeTemporaryExpr that has static storage duration, with no | 
|  | 7308 | //    CallIndex, for a lifetime-extended temporary. | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 7309 | // plus an offset in bytes. | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7310 | //===----------------------------------------------------------------------===// | 
|  | 7311 | namespace { | 
| Benjamin Kramer | 26222b6 | 2009-11-28 19:03:38 +0000 | [diff] [blame] | 7312 | class LValueExprEvaluator | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7313 | : public LValueExprEvaluatorBase<LValueExprEvaluator> { | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7314 | public: | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7315 | LValueExprEvaluator(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) : | 
|  | 7316 | LValueExprEvaluatorBaseTy(Info, Result, InvalidBaseOK) {} | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 7317 |  | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7318 | bool VisitVarDecl(const Expr *E, const VarDecl *VD); | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7319 | bool VisitUnaryPreIncDec(const UnaryOperator *UO); | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7320 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7321 | bool VisitDeclRefExpr(const DeclRefExpr *E); | 
|  | 7322 | bool VisitPredefinedExpr(const PredefinedExpr *E) { return Success(E); } | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 7323 | bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7324 | bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); | 
|  | 7325 | bool VisitMemberExpr(const MemberExpr *E); | 
|  | 7326 | bool VisitStringLiteral(const StringLiteral *E) { return Success(E); } | 
|  | 7327 | bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); } | 
| Richard Smith | 6e52514 | 2011-12-27 12:18:28 +0000 | [diff] [blame] | 7328 | bool VisitCXXTypeidExpr(const CXXTypeidExpr *E); | 
| Francois Pichet | 0066db9 | 2012-04-16 04:08:35 +0000 | [diff] [blame] | 7329 | bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7330 | bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); | 
|  | 7331 | bool VisitUnaryDeref(const UnaryOperator *E); | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 7332 | bool VisitUnaryReal(const UnaryOperator *E); | 
|  | 7333 | bool VisitUnaryImag(const UnaryOperator *E); | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7334 | bool VisitUnaryPreInc(const UnaryOperator *UO) { | 
|  | 7335 | return VisitUnaryPreIncDec(UO); | 
|  | 7336 | } | 
|  | 7337 | bool VisitUnaryPreDec(const UnaryOperator *UO) { | 
|  | 7338 | return VisitUnaryPreIncDec(UO); | 
|  | 7339 | } | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7340 | bool VisitBinAssign(const BinaryOperator *BO); | 
|  | 7341 | bool VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); | 
| Anders Carlsson | de55f64 | 2009-10-03 16:30:22 +0000 | [diff] [blame] | 7342 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7343 | bool VisitCastExpr(const CastExpr *E) { | 
| Anders Carlsson | de55f64 | 2009-10-03 16:30:22 +0000 | [diff] [blame] | 7344 | switch (E->getCastKind()) { | 
|  | 7345 | default: | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7346 | return LValueExprEvaluatorBaseTy::VisitCastExpr(E); | 
| Anders Carlsson | de55f64 | 2009-10-03 16:30:22 +0000 | [diff] [blame] | 7347 |  | 
| Eli Friedman | ce3e02a | 2011-10-11 00:13:24 +0000 | [diff] [blame] | 7348 | case CK_LValueBitCast: | 
| Richard Smith | 6d6ecc3 | 2011-12-12 12:46:16 +0000 | [diff] [blame] | 7349 | this->CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 7350 | if (!Visit(E->getSubExpr())) | 
|  | 7351 | return false; | 
|  | 7352 | Result.Designator.setInvalid(); | 
|  | 7353 | return true; | 
| Eli Friedman | ce3e02a | 2011-10-11 00:13:24 +0000 | [diff] [blame] | 7354 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7355 | case CK_BaseToDerived: | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7356 | if (!Visit(E->getSubExpr())) | 
|  | 7357 | return false; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7358 | return HandleBaseToDerivedCast(Info, E, Result); | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 7359 |  | 
|  | 7360 | case CK_Dynamic: | 
|  | 7361 | if (!Visit(E->getSubExpr())) | 
|  | 7362 | return false; | 
|  | 7363 | return HandleDynamicCast(Info, cast<ExplicitCastExpr>(E), Result); | 
| Anders Carlsson | de55f64 | 2009-10-03 16:30:22 +0000 | [diff] [blame] | 7364 | } | 
|  | 7365 | } | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7366 | }; | 
|  | 7367 | } // end anonymous namespace | 
|  | 7368 |  | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7369 | /// Evaluate an expression as an lvalue. This can be legitimately called on | 
| Nico Weber | 9677562 | 2015-09-15 23:17:17 +0000 | [diff] [blame] | 7370 | /// expressions which are not glvalues, in three cases: | 
| Richard Smith | 9f8400e | 2013-05-01 19:00:39 +0000 | [diff] [blame] | 7371 | ///  * function designators in C, and | 
|  | 7372 | ///  * "extern void" objects | 
| Nico Weber | 9677562 | 2015-09-15 23:17:17 +0000 | [diff] [blame] | 7373 | ///  * @selector() expressions in Objective-C | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7374 | static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, | 
|  | 7375 | bool InvalidBaseOK) { | 
| Richard Smith | 9f8400e | 2013-05-01 19:00:39 +0000 | [diff] [blame] | 7376 | assert(E->isGLValue() || E->getType()->isFunctionType() || | 
| Nico Weber | 9677562 | 2015-09-15 23:17:17 +0000 | [diff] [blame] | 7377 | E->getType()->isVoidType() || isa<ObjCSelectorExpr>(E)); | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7378 | return LValueExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7379 | } | 
|  | 7380 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7381 | bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { | 
| David Majnemer | 0c43d80 | 2014-06-25 08:15:07 +0000 | [diff] [blame] | 7382 | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 7383 | return Success(FD); | 
|  | 7384 | if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7385 | return VisitVarDecl(E, VD); | 
| Richard Smith | dca60b4 | 2016-08-12 00:39:32 +0000 | [diff] [blame] | 7386 | if (const BindingDecl *BD = dyn_cast<BindingDecl>(E->getDecl())) | 
| Richard Smith | 97fcf4b | 2016-08-14 23:15:52 +0000 | [diff] [blame] | 7387 | return Visit(BD->getBinding()); | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7388 | return Error(E); | 
|  | 7389 | } | 
| Richard Smith | 733237d | 2011-10-24 23:14:33 +0000 | [diff] [blame] | 7390 |  | 
| Faisal Vali | 0528a31 | 2016-11-13 06:09:16 +0000 | [diff] [blame] | 7391 |  | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7392 | bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 7393 |  | 
|  | 7394 | // If we are within a lambda's call operator, check whether the 'VD' referred | 
|  | 7395 | // to within 'E' actually represents a lambda-capture that maps to a | 
|  | 7396 | // data-member/field within the closure object, and if so, evaluate to the | 
|  | 7397 | // field or what the field refers to. | 
| Erik Pilkington | 1123291 | 2018-04-05 00:12:05 +0000 | [diff] [blame] | 7398 | if (Info.CurrentCall && isLambdaCallOperator(Info.CurrentCall->Callee) && | 
|  | 7399 | isa<DeclRefExpr>(E) && | 
|  | 7400 | cast<DeclRefExpr>(E)->refersToEnclosingVariableOrCapture()) { | 
|  | 7401 | // We don't always have a complete capture-map when checking or inferring if | 
|  | 7402 | // the function call operator meets the requirements of a constexpr function | 
|  | 7403 | // - but we don't need to evaluate the captures to determine constexprness | 
|  | 7404 | // (dcl.constexpr C++17). | 
|  | 7405 | if (Info.checkingPotentialConstantExpression()) | 
|  | 7406 | return false; | 
|  | 7407 |  | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 7408 | if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 7409 | // Start with 'Result' referring to the complete closure object... | 
|  | 7410 | Result = *Info.CurrentCall->This; | 
|  | 7411 | // ... then update it to refer to the field of the closure object | 
|  | 7412 | // that represents the capture. | 
|  | 7413 | if (!HandleLValueMember(Info, E, Result, FD)) | 
|  | 7414 | return false; | 
|  | 7415 | // And if the field is of reference type, update 'Result' to refer to what | 
|  | 7416 | // the field refers to. | 
|  | 7417 | if (FD->getType()->isReferenceType()) { | 
|  | 7418 | APValue RVal; | 
|  | 7419 | if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result, | 
|  | 7420 | RVal)) | 
|  | 7421 | return false; | 
|  | 7422 | Result.setFrom(Info.Ctx, RVal); | 
|  | 7423 | } | 
|  | 7424 | return true; | 
|  | 7425 | } | 
|  | 7426 | } | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 7427 | CallStackFrame *Frame = nullptr; | 
| Faisal Vali | 0528a31 | 2016-11-13 06:09:16 +0000 | [diff] [blame] | 7428 | if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) { | 
|  | 7429 | // Only if a local variable was declared in the function currently being | 
|  | 7430 | // evaluated, do we expect to be able to find its value in the current | 
|  | 7431 | // frame. (Otherwise it was likely declared in an enclosing context and | 
|  | 7432 | // could either have a valid evaluatable value (for e.g. a constexpr | 
|  | 7433 | // variable) or be ill-formed (and trigger an appropriate evaluation | 
|  | 7434 | // diagnostic)). | 
|  | 7435 | if (Info.CurrentCall->Callee && | 
|  | 7436 | Info.CurrentCall->Callee->Equals(VD->getDeclContext())) { | 
|  | 7437 | Frame = Info.CurrentCall; | 
|  | 7438 | } | 
|  | 7439 | } | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7440 |  | 
| Richard Smith | fec0992 | 2011-11-01 16:57:24 +0000 | [diff] [blame] | 7441 | if (!VD->getType()->isReferenceType()) { | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7442 | if (Frame) { | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 7443 | Result.set({VD, Frame->Index, | 
|  | 7444 | Info.CurrentCall->getCurrentTemporaryVersion(VD)}); | 
| Richard Smith | fec0992 | 2011-11-01 16:57:24 +0000 | [diff] [blame] | 7445 | return true; | 
|  | 7446 | } | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 7447 | return Success(VD); | 
| Richard Smith | fec0992 | 2011-11-01 16:57:24 +0000 | [diff] [blame] | 7448 | } | 
| Eli Friedman | 751aa72b7 | 2009-05-27 06:04:58 +0000 | [diff] [blame] | 7449 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7450 | APValue *V; | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 7451 | if (!evaluateVarDeclInit(Info, E, VD, Frame, V, nullptr)) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 7452 | return false; | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 7453 | if (!V->hasValue()) { | 
|  | 7454 | // FIXME: Is it possible for V to be indeterminate here? If so, we should | 
|  | 7455 | // adjust the diagnostic to say that. | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 7456 | if (!Info.checkingPotentialConstantExpression()) | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 7457 | Info.FFDiag(E, diag::note_constexpr_use_uninit_reference); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 7458 | return false; | 
|  | 7459 | } | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7460 | return Success(*V, E); | 
| Anders Carlsson | a42ee44 | 2008-11-24 04:41:22 +0000 | [diff] [blame] | 7461 | } | 
|  | 7462 |  | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 7463 | bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( | 
|  | 7464 | const MaterializeTemporaryExpr *E) { | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7465 | // Walk through the expression to find the materialized temporary itself. | 
|  | 7466 | SmallVector<const Expr *, 2> CommaLHSs; | 
|  | 7467 | SmallVector<SubobjectAdjustment, 2> Adjustments; | 
| Tyker | b0561b3 | 2019-11-17 11:41:55 +0100 | [diff] [blame] | 7468 | const Expr *Inner = | 
|  | 7469 | E->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7470 |  | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7471 | // If we passed any comma operators, evaluate their LHSs. | 
|  | 7472 | for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I) | 
|  | 7473 | if (!EvaluateIgnoredValue(Info, CommaLHSs[I])) | 
|  | 7474 | return false; | 
|  | 7475 |  | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 7476 | // A materialized temporary with static storage duration can appear within the | 
|  | 7477 | // result of a constant expression evaluation, so we need to preserve its | 
|  | 7478 | // value for use outside this evaluation. | 
|  | 7479 | APValue *Value; | 
|  | 7480 | if (E->getStorageDuration() == SD_Static) { | 
| Tyker | b0561b3 | 2019-11-17 11:41:55 +0100 | [diff] [blame] | 7481 | Value = E->getOrCreateValue(true); | 
| Richard Smith | a509f2f | 2013-06-14 03:07:01 +0000 | [diff] [blame] | 7482 | *Value = APValue(); | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 7483 | Result.set(E); | 
|  | 7484 | } else { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 7485 | Value = &Info.CurrentCall->createTemporary( | 
|  | 7486 | E, E->getType(), E->getStorageDuration() == SD_Automatic, Result); | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 7487 | } | 
|  | 7488 |  | 
| Richard Smith | ea4ad5d | 2013-06-06 08:19:16 +0000 | [diff] [blame] | 7489 | QualType Type = Inner->getType(); | 
|  | 7490 |  | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7491 | // Materialize the temporary itself. | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 7492 | if (!EvaluateInPlace(*Value, Info, Result, Inner)) { | 
| Richard Smith | ea4ad5d | 2013-06-06 08:19:16 +0000 | [diff] [blame] | 7493 | *Value = APValue(); | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7494 | return false; | 
| Richard Smith | ea4ad5d | 2013-06-06 08:19:16 +0000 | [diff] [blame] | 7495 | } | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7496 |  | 
|  | 7497 | // Adjust our lvalue to refer to the desired subobject. | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7498 | for (unsigned I = Adjustments.size(); I != 0; /**/) { | 
|  | 7499 | --I; | 
|  | 7500 | switch (Adjustments[I].Kind) { | 
|  | 7501 | case SubobjectAdjustment::DerivedToBaseAdjustment: | 
|  | 7502 | if (!HandleLValueBasePath(Info, Adjustments[I].DerivedToBase.BasePath, | 
|  | 7503 | Type, Result)) | 
|  | 7504 | return false; | 
|  | 7505 | Type = Adjustments[I].DerivedToBase.BasePath->getType(); | 
|  | 7506 | break; | 
|  | 7507 |  | 
|  | 7508 | case SubobjectAdjustment::FieldAdjustment: | 
|  | 7509 | if (!HandleLValueMember(Info, E, Result, Adjustments[I].Field)) | 
|  | 7510 | return false; | 
|  | 7511 | Type = Adjustments[I].Field->getType(); | 
|  | 7512 | break; | 
|  | 7513 |  | 
|  | 7514 | case SubobjectAdjustment::MemberPointerAdjustment: | 
|  | 7515 | if (!HandleMemberPointerAccess(this->Info, Type, Result, | 
|  | 7516 | Adjustments[I].Ptr.RHS)) | 
|  | 7517 | return false; | 
|  | 7518 | Type = Adjustments[I].Ptr.MPT->getPointeeType(); | 
|  | 7519 | break; | 
|  | 7520 | } | 
|  | 7521 | } | 
|  | 7522 |  | 
|  | 7523 | return true; | 
| Richard Smith | 4e4c78ff | 2011-10-31 05:52:43 +0000 | [diff] [blame] | 7524 | } | 
|  | 7525 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7526 | bool | 
|  | 7527 | LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { | 
| Richard Smith | b3189a1 | 2016-12-05 07:49:14 +0000 | [diff] [blame] | 7528 | assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) && | 
|  | 7529 | "lvalue compound literal in c++?"); | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7530 | // Defer visiting the literal until the lvalue-to-rvalue conversion. We can | 
|  | 7531 | // only see this when folding in C, so there's no standard to follow here. | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7532 | return Success(E); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7533 | } | 
|  | 7534 |  | 
| Richard Smith | 6e52514 | 2011-12-27 12:18:28 +0000 | [diff] [blame] | 7535 | bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { | 
| Richard Smith | a933030 | 2019-05-17 19:19:28 +0000 | [diff] [blame] | 7536 | TypeInfoLValue TypeInfo; | 
|  | 7537 |  | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 7538 | if (!E->isPotentiallyEvaluated()) { | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 7539 | if (E->isTypeOperand()) | 
|  | 7540 | TypeInfo = TypeInfoLValue(E->getTypeOperand(Info.Ctx).getTypePtr()); | 
|  | 7541 | else | 
|  | 7542 | TypeInfo = TypeInfoLValue(E->getExprOperand()->getType().getTypePtr()); | 
| Richard Smith | a933030 | 2019-05-17 19:19:28 +0000 | [diff] [blame] | 7543 | } else { | 
|  | 7544 | if (!Info.Ctx.getLangOpts().CPlusPlus2a) { | 
|  | 7545 | Info.CCEDiag(E, diag::note_constexpr_typeid_polymorphic) | 
|  | 7546 | << E->getExprOperand()->getType() | 
|  | 7547 | << E->getExprOperand()->getSourceRange(); | 
|  | 7548 | } | 
|  | 7549 |  | 
|  | 7550 | if (!Visit(E->getExprOperand())) | 
|  | 7551 | return false; | 
|  | 7552 |  | 
|  | 7553 | Optional<DynamicType> DynType = | 
|  | 7554 | ComputeDynamicType(Info, E, Result, AK_TypeId); | 
|  | 7555 | if (!DynType) | 
|  | 7556 | return false; | 
|  | 7557 |  | 
|  | 7558 | TypeInfo = | 
|  | 7559 | TypeInfoLValue(Info.Ctx.getRecordType(DynType->Type).getTypePtr()); | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 7560 | } | 
| Richard Smith | 6f3d435 | 2012-10-17 23:52:07 +0000 | [diff] [blame] | 7561 |  | 
| Richard Smith | a933030 | 2019-05-17 19:19:28 +0000 | [diff] [blame] | 7562 | return Success(APValue::LValueBase::getTypeInfo(TypeInfo, E->getType())); | 
| Richard Smith | 6e52514 | 2011-12-27 12:18:28 +0000 | [diff] [blame] | 7563 | } | 
|  | 7564 |  | 
| Francois Pichet | 0066db9 | 2012-04-16 04:08:35 +0000 | [diff] [blame] | 7565 | bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { | 
|  | 7566 | return Success(E); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7567 | } | 
| Francois Pichet | 0066db9 | 2012-04-16 04:08:35 +0000 | [diff] [blame] | 7568 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7569 | bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7570 | // Handle static data members. | 
|  | 7571 | if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) { | 
| David Majnemer | e9807b2 | 2016-02-26 04:23:19 +0000 | [diff] [blame] | 7572 | VisitIgnoredBaseExpression(E->getBase()); | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7573 | return VisitVarDecl(E, VD); | 
|  | 7574 | } | 
|  | 7575 |  | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 7576 | // Handle static member functions. | 
|  | 7577 | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) { | 
|  | 7578 | if (MD->isStatic()) { | 
| David Majnemer | e9807b2 | 2016-02-26 04:23:19 +0000 | [diff] [blame] | 7579 | VisitIgnoredBaseExpression(E->getBase()); | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 7580 | return Success(MD); | 
| Richard Smith | 254a73d | 2011-10-28 22:34:42 +0000 | [diff] [blame] | 7581 | } | 
|  | 7582 | } | 
|  | 7583 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7584 | // Handle non-static data members. | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7585 | return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7586 | } | 
|  | 7587 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7588 | bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7589 | // FIXME: Deal with vectors as array subscript bases. | 
|  | 7590 | if (E->getBase()->getType()->isVectorType()) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 7591 | return Error(E); | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7592 |  | 
| Nick Lewycky | ad88868 | 2017-04-27 07:27:36 +0000 | [diff] [blame] | 7593 | bool Success = true; | 
|  | 7594 | if (!evaluatePointer(E->getBase(), Result)) { | 
|  | 7595 | if (!Info.noteFailure()) | 
|  | 7596 | return false; | 
|  | 7597 | Success = false; | 
|  | 7598 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 7599 |  | 
| Anders Carlsson | 9f9e424 | 2008-11-16 19:01:22 +0000 | [diff] [blame] | 7600 | APSInt Index; | 
|  | 7601 | if (!EvaluateInteger(E->getIdx(), Index, Info)) | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7602 | return false; | 
| Anders Carlsson | 9f9e424 | 2008-11-16 19:01:22 +0000 | [diff] [blame] | 7603 |  | 
| Nick Lewycky | ad88868 | 2017-04-27 07:27:36 +0000 | [diff] [blame] | 7604 | return Success && | 
|  | 7605 | HandleLValueArrayAdjustment(Info, E, Result, E->getType(), Index); | 
| Anders Carlsson | 9f9e424 | 2008-11-16 19:01:22 +0000 | [diff] [blame] | 7606 | } | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7607 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7608 | bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7609 | return evaluatePointer(E->getSubExpr(), Result); | 
| Eli Friedman | 0b8337c | 2009-02-20 01:57:15 +0000 | [diff] [blame] | 7610 | } | 
|  | 7611 |  | 
| Richard Smith | 66c9699 | 2012-02-18 22:04:06 +0000 | [diff] [blame] | 7612 | bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { | 
|  | 7613 | if (!Visit(E->getSubExpr())) | 
|  | 7614 | return false; | 
|  | 7615 | // __real is a no-op on scalar lvalues. | 
|  | 7616 | if (E->getSubExpr()->getType()->isAnyComplexType()) | 
|  | 7617 | HandleLValueComplexElement(Info, E, Result, E->getType(), false); | 
|  | 7618 | return true; | 
|  | 7619 | } | 
|  | 7620 |  | 
|  | 7621 | bool LValueExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { | 
|  | 7622 | assert(E->getSubExpr()->getType()->isAnyComplexType() && | 
|  | 7623 | "lvalue __imag__ on scalar?"); | 
|  | 7624 | if (!Visit(E->getSubExpr())) | 
|  | 7625 | return false; | 
|  | 7626 | HandleLValueComplexElement(Info, E, Result, E->getType(), true); | 
|  | 7627 | return true; | 
|  | 7628 | } | 
|  | 7629 |  | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7630 | bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) { | 
| Aaron Ballman | dd69ef3 | 2014-08-19 15:55:55 +0000 | [diff] [blame] | 7631 | if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7632 | return Error(UO); | 
|  | 7633 |  | 
|  | 7634 | if (!this->Visit(UO->getSubExpr())) | 
|  | 7635 | return false; | 
|  | 7636 |  | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7637 | return handleIncDec( | 
|  | 7638 | this->Info, UO, Result, UO->getSubExpr()->getType(), | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 7639 | UO->isIncrementOp(), nullptr); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7640 | } | 
|  | 7641 |  | 
|  | 7642 | bool LValueExprEvaluator::VisitCompoundAssignOperator( | 
|  | 7643 | const CompoundAssignOperator *CAO) { | 
| Aaron Ballman | dd69ef3 | 2014-08-19 15:55:55 +0000 | [diff] [blame] | 7644 | if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7645 | return Error(CAO); | 
|  | 7646 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7647 | APValue RHS; | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7648 |  | 
|  | 7649 | // The overall lvalue result is the result of evaluating the LHS. | 
|  | 7650 | if (!this->Visit(CAO->getLHS())) { | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 7651 | if (Info.noteFailure()) | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7652 | Evaluate(RHS, this->Info, CAO->getRHS()); | 
|  | 7653 | return false; | 
|  | 7654 | } | 
|  | 7655 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7656 | if (!Evaluate(RHS, this->Info, CAO->getRHS())) | 
|  | 7657 | return false; | 
|  | 7658 |  | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 7659 | return handleCompoundAssignment( | 
|  | 7660 | this->Info, CAO, | 
|  | 7661 | Result, CAO->getLHS()->getType(), CAO->getComputationLHSType(), | 
|  | 7662 | CAO->getOpForCompoundAssignment(CAO->getOpcode()), RHS); | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7663 | } | 
|  | 7664 |  | 
|  | 7665 | bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { | 
| Aaron Ballman | dd69ef3 | 2014-08-19 15:55:55 +0000 | [diff] [blame] | 7666 | if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7667 | return Error(E); | 
|  | 7668 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7669 | APValue NewVal; | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7670 |  | 
|  | 7671 | if (!this->Visit(E->getLHS())) { | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 7672 | if (Info.noteFailure()) | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7673 | Evaluate(NewVal, this->Info, E->getRHS()); | 
|  | 7674 | return false; | 
|  | 7675 | } | 
|  | 7676 |  | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7677 | if (!Evaluate(NewVal, this->Info, E->getRHS())) | 
|  | 7678 | return false; | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7679 |  | 
| Richard Smith | 31c69a3 | 2019-05-21 23:15:20 +0000 | [diff] [blame] | 7680 | if (Info.getLangOpts().CPlusPlus2a && | 
|  | 7681 | !HandleUnionActiveMemberChange(Info, E->getLHS(), Result)) | 
|  | 7682 | return false; | 
|  | 7683 |  | 
| Richard Smith | 243ef90 | 2013-05-05 23:31:59 +0000 | [diff] [blame] | 7684 | return handleAssignment(this->Info, E, Result, E->getLHS()->getType(), | 
| Richard Smith | 3229b74 | 2013-05-05 21:17:10 +0000 | [diff] [blame] | 7685 | NewVal); | 
|  | 7686 | } | 
|  | 7687 |  | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7688 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 7689 | // Pointer Evaluation | 
|  | 7690 | //===----------------------------------------------------------------------===// | 
|  | 7691 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 7692 | /// Attempts to compute the number of bytes available at the pointer | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7693 | /// returned by a function with the alloc_size attribute. Returns true if we | 
|  | 7694 | /// were successful. Places an unsigned number into `Result`. | 
|  | 7695 | /// | 
|  | 7696 | /// This expects the given CallExpr to be a call to a function with an | 
|  | 7697 | /// alloc_size attribute. | 
|  | 7698 | static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, | 
|  | 7699 | const CallExpr *Call, | 
|  | 7700 | llvm::APInt &Result) { | 
|  | 7701 | const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call); | 
|  | 7702 |  | 
| Joel E. Denny | 8150810 | 2018-03-13 14:51:22 +0000 | [diff] [blame] | 7703 | assert(AllocSize && AllocSize->getElemSizeParam().isValid()); | 
|  | 7704 | unsigned SizeArgNo = AllocSize->getElemSizeParam().getASTIndex(); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7705 | unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType()); | 
|  | 7706 | if (Call->getNumArgs() <= SizeArgNo) | 
|  | 7707 | return false; | 
|  | 7708 |  | 
|  | 7709 | auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) { | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 7710 | Expr::EvalResult ExprResult; | 
|  | 7711 | if (!E->EvaluateAsInt(ExprResult, Ctx, Expr::SE_AllowSideEffects)) | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7712 | return false; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 7713 | Into = ExprResult.Val.getInt(); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7714 | if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) | 
|  | 7715 | return false; | 
|  | 7716 | Into = Into.zextOrSelf(BitsInSizeT); | 
|  | 7717 | return true; | 
|  | 7718 | }; | 
|  | 7719 |  | 
|  | 7720 | APSInt SizeOfElem; | 
|  | 7721 | if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem)) | 
|  | 7722 | return false; | 
|  | 7723 |  | 
| Joel E. Denny | 8150810 | 2018-03-13 14:51:22 +0000 | [diff] [blame] | 7724 | if (!AllocSize->getNumElemsParam().isValid()) { | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7725 | Result = std::move(SizeOfElem); | 
|  | 7726 | return true; | 
|  | 7727 | } | 
|  | 7728 |  | 
|  | 7729 | APSInt NumberOfElems; | 
| Joel E. Denny | 8150810 | 2018-03-13 14:51:22 +0000 | [diff] [blame] | 7730 | unsigned NumArgNo = AllocSize->getNumElemsParam().getASTIndex(); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7731 | if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems)) | 
|  | 7732 | return false; | 
|  | 7733 |  | 
|  | 7734 | bool Overflow; | 
|  | 7735 | llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow); | 
|  | 7736 | if (Overflow) | 
|  | 7737 | return false; | 
|  | 7738 |  | 
|  | 7739 | Result = std::move(BytesAvailable); | 
|  | 7740 | return true; | 
|  | 7741 | } | 
|  | 7742 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 7743 | /// Convenience function. LVal's base must be a call to an alloc_size | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7744 | /// function. | 
|  | 7745 | static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, | 
|  | 7746 | const LValue &LVal, | 
|  | 7747 | llvm::APInt &Result) { | 
|  | 7748 | assert(isBaseAnAllocSizeCall(LVal.getLValueBase()) && | 
|  | 7749 | "Can't get the size of a non alloc_size function"); | 
|  | 7750 | const auto *Base = LVal.getLValueBase().get<const Expr *>(); | 
|  | 7751 | const CallExpr *CE = tryUnwrapAllocSizeCall(Base); | 
|  | 7752 | return getBytesReturnedByAllocSizeCall(Ctx, CE, Result); | 
|  | 7753 | } | 
|  | 7754 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 7755 | /// Attempts to evaluate the given LValueBase as the result of a call to | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7756 | /// a function with the alloc_size attribute. If it was possible to do so, this | 
|  | 7757 | /// function will return true, make Result's Base point to said function call, | 
|  | 7758 | /// and mark Result's Base as invalid. | 
|  | 7759 | static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base, | 
|  | 7760 | LValue &Result) { | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7761 | if (Base.isNull()) | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7762 | return false; | 
|  | 7763 |  | 
|  | 7764 | // Because we do no form of static analysis, we only support const variables. | 
|  | 7765 | // | 
|  | 7766 | // Additionally, we can't support parameters, nor can we support static | 
|  | 7767 | // variables (in the latter case, use-before-assign isn't UB; in the former, | 
|  | 7768 | // we have no clue what they'll be assigned to). | 
|  | 7769 | const auto *VD = | 
|  | 7770 | dyn_cast_or_null<VarDecl>(Base.dyn_cast<const ValueDecl *>()); | 
|  | 7771 | if (!VD || !VD->isLocalVarDecl() || !VD->getType().isConstQualified()) | 
|  | 7772 | return false; | 
|  | 7773 |  | 
|  | 7774 | const Expr *Init = VD->getAnyInitializer(); | 
|  | 7775 | if (!Init) | 
|  | 7776 | return false; | 
|  | 7777 |  | 
|  | 7778 | const Expr *E = Init->IgnoreParens(); | 
|  | 7779 | if (!tryUnwrapAllocSizeCall(E)) | 
|  | 7780 | return false; | 
|  | 7781 |  | 
|  | 7782 | // Store E instead of E unwrapped so that the type of the LValue's base is | 
|  | 7783 | // what the user wanted. | 
|  | 7784 | Result.setInvalid(E); | 
|  | 7785 |  | 
|  | 7786 | QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType(); | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 7787 | Result.addUnsizedArray(Info, E, Pointee); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7788 | return true; | 
|  | 7789 | } | 
|  | 7790 |  | 
| Anders Carlsson | 0a1707c | 2008-07-08 05:13:58 +0000 | [diff] [blame] | 7791 | namespace { | 
| Benjamin Kramer | 26222b6 | 2009-11-28 19:03:38 +0000 | [diff] [blame] | 7792 | class PointerExprEvaluator | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 7793 | : public ExprEvaluatorBase<PointerExprEvaluator> { | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7794 | LValue &Result; | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7795 | bool InvalidBaseOK; | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7796 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7797 | bool Success(const Expr *E) { | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 7798 | Result.set(E); | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7799 | return true; | 
|  | 7800 | } | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7801 |  | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7802 | bool evaluateLValue(const Expr *E, LValue &Result) { | 
|  | 7803 | return EvaluateLValue(E, Result, Info, InvalidBaseOK); | 
|  | 7804 | } | 
|  | 7805 |  | 
|  | 7806 | bool evaluatePointer(const Expr *E, LValue &Result) { | 
|  | 7807 | return EvaluatePointer(E, Result, Info, InvalidBaseOK); | 
|  | 7808 | } | 
|  | 7809 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 7810 | bool visitNonBuiltinCallExpr(const CallExpr *E); | 
| Anders Carlsson | b5ad021 | 2008-07-08 14:30:00 +0000 | [diff] [blame] | 7811 | public: | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 7812 |  | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7813 | PointerExprEvaluator(EvalInfo &info, LValue &Result, bool InvalidBaseOK) | 
|  | 7814 | : ExprEvaluatorBaseTy(info), Result(Result), | 
|  | 7815 | InvalidBaseOK(InvalidBaseOK) {} | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 7816 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 7817 | bool Success(const APValue &V, const Expr *E) { | 
|  | 7818 | Result.setFrom(Info.Ctx, V); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7819 | return true; | 
|  | 7820 | } | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 7821 | bool ZeroInitialization(const Expr *E) { | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 7822 | Result.setNull(Info.Ctx, E->getType()); | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 7823 | return true; | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 7824 | } | 
| Anders Carlsson | b5ad021 | 2008-07-08 14:30:00 +0000 | [diff] [blame] | 7825 |  | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7826 | bool VisitBinaryOperator(const BinaryOperator *E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7827 | bool VisitCastExpr(const CastExpr* E); | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7828 | bool VisitUnaryAddrOf(const UnaryOperator *E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7829 | bool VisitObjCStringLiteral(const ObjCStringLiteral *E) | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7830 | { return Success(E); } | 
| Nick Lewycky | 19ae6dc | 2017-04-29 00:07:27 +0000 | [diff] [blame] | 7831 | bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { | 
| Akira Hatanaka | 1488ee4 | 2019-03-08 04:45:37 +0000 | [diff] [blame] | 7832 | if (E->isExpressibleAsConstantInitializer()) | 
|  | 7833 | return Success(E); | 
| Nick Lewycky | 19ae6dc | 2017-04-29 00:07:27 +0000 | [diff] [blame] | 7834 | if (Info.noteFailure()) | 
|  | 7835 | EvaluateIgnoredValue(Info, E->getSubExpr()); | 
|  | 7836 | return Error(E); | 
|  | 7837 | } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7838 | bool VisitAddrLabelExpr(const AddrLabelExpr *E) | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7839 | { return Success(E); } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7840 | bool VisitCallExpr(const CallExpr *E); | 
| Richard Smith | 6328cbd | 2016-11-16 00:57:23 +0000 | [diff] [blame] | 7841 | bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 7842 | bool VisitBlockExpr(const BlockExpr *E) { | 
| John McCall | c63de66 | 2011-02-02 13:00:07 +0000 | [diff] [blame] | 7843 | if (!E->getBlockDecl()->hasCaptures()) | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7844 | return Success(E); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 7845 | return Error(E); | 
| Mike Stump | a670332 | 2009-02-19 22:01:56 +0000 | [diff] [blame] | 7846 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7847 | bool VisitCXXThisExpr(const CXXThisExpr *E) { | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7848 | // Can't look at 'this' when checking a potential constant expression. | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 7849 | if (Info.checkingPotentialConstantExpression()) | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7850 | return false; | 
| Richard Smith | 22a5d61 | 2014-07-07 06:00:13 +0000 | [diff] [blame] | 7851 | if (!Info.CurrentCall->This) { | 
|  | 7852 | if (Info.getLangOpts().CPlusPlus11) | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 7853 | Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); | 
| Richard Smith | 22a5d61 | 2014-07-07 06:00:13 +0000 | [diff] [blame] | 7854 | else | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 7855 | Info.FFDiag(E); | 
| Richard Smith | 22a5d61 | 2014-07-07 06:00:13 +0000 | [diff] [blame] | 7856 | return false; | 
|  | 7857 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7858 | Result = *Info.CurrentCall->This; | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 7859 | // If we are inside a lambda's call operator, the 'this' expression refers | 
|  | 7860 | // to the enclosing '*this' object (either by value or reference) which is | 
|  | 7861 | // either copied into the closure object's field that represents the '*this' | 
|  | 7862 | // or refers to '*this'. | 
|  | 7863 | if (isLambdaCallOperator(Info.CurrentCall->Callee)) { | 
| James Y Knight | 90fce46 | 2019-12-03 23:32:57 -0500 | [diff] [blame] | 7864 | // Ensure we actually have captured 'this'. (an error will have | 
|  | 7865 | // been previously reported if not). | 
|  | 7866 | if (!Info.CurrentCall->LambdaThisCaptureField) | 
|  | 7867 | return false; | 
|  | 7868 |  | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 7869 | // Update 'Result' to refer to the data member/field of the closure object | 
|  | 7870 | // that represents the '*this' capture. | 
|  | 7871 | if (!HandleLValueMember(Info, E, Result, | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 7872 | Info.CurrentCall->LambdaThisCaptureField)) | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 7873 | return false; | 
|  | 7874 | // If we captured '*this' by reference, replace the field with its referent. | 
|  | 7875 | if (Info.CurrentCall->LambdaThisCaptureField->getType() | 
|  | 7876 | ->isPointerType()) { | 
|  | 7877 | APValue RVal; | 
|  | 7878 | if (!handleLValueToRValueConversion(Info, E, E->getType(), Result, | 
|  | 7879 | RVal)) | 
|  | 7880 | return false; | 
|  | 7881 |  | 
|  | 7882 | Result.setFrom(Info.Ctx, RVal); | 
|  | 7883 | } | 
|  | 7884 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7885 | return true; | 
|  | 7886 | } | 
| John McCall | c07a0c7 | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 7887 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 7888 | bool VisitCXXNewExpr(const CXXNewExpr *E); | 
|  | 7889 |  | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 7890 | bool VisitSourceLocExpr(const SourceLocExpr *E) { | 
|  | 7891 | assert(E->isStringType() && "SourceLocExpr isn't a pointer type?"); | 
|  | 7892 | APValue LValResult = E->EvaluateInContext( | 
|  | 7893 | Info.Ctx, Info.CurrentCall->CurSourceLocExprScope.getDefaultExpr()); | 
|  | 7894 | Result.setFrom(Info.Ctx, LValResult); | 
|  | 7895 | return true; | 
|  | 7896 | } | 
|  | 7897 |  | 
| Eli Friedman | 449fe54 | 2009-03-23 04:56:01 +0000 | [diff] [blame] | 7898 | // FIXME: Missing: @protocol, @selector | 
| Anders Carlsson | 4a3585b | 2008-07-08 15:34:11 +0000 | [diff] [blame] | 7899 | }; | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 7900 | } // end anonymous namespace | 
| Anders Carlsson | 4a3585b | 2008-07-08 15:34:11 +0000 | [diff] [blame] | 7901 |  | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7902 | static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info, | 
|  | 7903 | bool InvalidBaseOK) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 7904 | assert(E->isRValue() && E->getType()->hasPointerRepresentation()); | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7905 | return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 7906 | } | 
|  | 7907 |  | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7908 | bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 7909 | if (E->getOpcode() != BO_Add && | 
|  | 7910 | E->getOpcode() != BO_Sub) | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7911 | return ExprEvaluatorBaseTy::VisitBinaryOperator(E); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 7912 |  | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 7913 | const Expr *PExp = E->getLHS(); | 
|  | 7914 | const Expr *IExp = E->getRHS(); | 
|  | 7915 | if (IExp->getType()->isPointerType()) | 
|  | 7916 | std::swap(PExp, IExp); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 7917 |  | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7918 | bool EvalPtrOK = evaluatePointer(PExp, Result); | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 7919 | if (!EvalPtrOK && !Info.noteFailure()) | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7920 | return false; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 7921 |  | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7922 | llvm::APSInt Offset; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 7923 | if (!EvaluateInteger(IExp, Offset, Info) || !EvalPtrOK) | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7924 | return false; | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 7925 |  | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 7926 | if (E->getOpcode() == BO_Sub) | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 7927 | negateAsSigned(Offset); | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 7928 |  | 
| Ted Kremenek | 2883175 | 2012-08-23 20:46:57 +0000 | [diff] [blame] | 7929 | QualType Pointee = PExp->getType()->castAs<PointerType>()->getPointeeType(); | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 7930 | return HandleLValueArrayAdjustment(Info, E, Result, Pointee, Offset); | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 7931 | } | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7932 |  | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 7933 | bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7934 | return evaluateLValue(E->getSubExpr(), Result); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 7935 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 7936 |  | 
| Richard Smith | 81dfef9 | 2018-07-11 00:29:05 +0000 | [diff] [blame] | 7937 | bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { | 
|  | 7938 | const Expr *SubExpr = E->getSubExpr(); | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 7939 |  | 
| Eli Friedman | 847a2bc | 2009-12-27 05:43:15 +0000 | [diff] [blame] | 7940 | switch (E->getCastKind()) { | 
|  | 7941 | default: | 
|  | 7942 | break; | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 7943 | case CK_BitCast: | 
| John McCall | 9320b87 | 2011-09-09 05:25:32 +0000 | [diff] [blame] | 7944 | case CK_CPointerToObjCPointerCast: | 
|  | 7945 | case CK_BlockPointerToObjCPointerCast: | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 7946 | case CK_AnyPointerToBlockPointerCast: | 
| Anastasia Stulova | 5d8ad8a | 2014-11-26 15:36:41 +0000 | [diff] [blame] | 7947 | case CK_AddressSpaceConversion: | 
| Richard Smith | b19ac0d | 2012-01-15 03:25:41 +0000 | [diff] [blame] | 7948 | if (!Visit(SubExpr)) | 
|  | 7949 | return false; | 
| Richard Smith | 6d6ecc3 | 2011-12-12 12:46:16 +0000 | [diff] [blame] | 7950 | // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are | 
|  | 7951 | // permitted in constant expressions in C++11. Bitcasts from cv void* are | 
|  | 7952 | // also static_casts, but we disallow them as a resolution to DR1312. | 
| Richard Smith | ff07af1 | 2011-12-12 19:10:03 +0000 | [diff] [blame] | 7953 | if (!E->getType()->isVoidPointerType()) { | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 7954 | if (!Result.InvalidBase && !Result.Designator.Invalid && | 
|  | 7955 | !Result.IsNullPtr && | 
|  | 7956 | Info.Ctx.hasSameUnqualifiedType(Result.Designator.getType(Info.Ctx), | 
|  | 7957 | E->getType()->getPointeeType()) && | 
|  | 7958 | Info.getStdAllocatorCaller("allocate")) { | 
|  | 7959 | // Inside a call to std::allocator::allocate and friends, we permit | 
|  | 7960 | // casting from void* back to cv1 T* for a pointer that points to a | 
|  | 7961 | // cv2 T. | 
|  | 7962 | } else { | 
|  | 7963 | Result.Designator.setInvalid(); | 
|  | 7964 | if (SubExpr->getType()->isVoidPointerType()) | 
|  | 7965 | CCEDiag(E, diag::note_constexpr_invalid_cast) | 
|  | 7966 | << 3 << SubExpr->getType(); | 
|  | 7967 | else | 
|  | 7968 | CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; | 
|  | 7969 | } | 
| Richard Smith | ff07af1 | 2011-12-12 19:10:03 +0000 | [diff] [blame] | 7970 | } | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 7971 | if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) | 
|  | 7972 | ZeroInitialization(E); | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 7973 | return true; | 
| Eli Friedman | 847a2bc | 2009-12-27 05:43:15 +0000 | [diff] [blame] | 7974 |  | 
| Anders Carlsson | 1827509 | 2010-10-31 20:41:46 +0000 | [diff] [blame] | 7975 | case CK_DerivedToBase: | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7976 | case CK_UncheckedDerivedToBase: | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 7977 | if (!evaluatePointer(E->getSubExpr(), Result)) | 
| Anders Carlsson | 1827509 | 2010-10-31 20:41:46 +0000 | [diff] [blame] | 7978 | return false; | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7979 | if (!Result.Base && Result.Offset.isZero()) | 
|  | 7980 | return true; | 
| Anders Carlsson | 1827509 | 2010-10-31 20:41:46 +0000 | [diff] [blame] | 7981 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 7982 | // Now figure out the necessary offset to add to the base LV to get from | 
| Anders Carlsson | 1827509 | 2010-10-31 20:41:46 +0000 | [diff] [blame] | 7983 | // the derived class to the base class. | 
| Richard Smith | 8440104 | 2013-06-03 05:03:02 +0000 | [diff] [blame] | 7984 | return HandleLValueBasePath(Info, E, E->getSubExpr()->getType()-> | 
|  | 7985 | castAs<PointerType>()->getPointeeType(), | 
|  | 7986 | Result); | 
| Anders Carlsson | 1827509 | 2010-10-31 20:41:46 +0000 | [diff] [blame] | 7987 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 7988 | case CK_BaseToDerived: | 
|  | 7989 | if (!Visit(E->getSubExpr())) | 
|  | 7990 | return false; | 
|  | 7991 | if (!Result.Base && Result.Offset.isZero()) | 
|  | 7992 | return true; | 
|  | 7993 | return HandleBaseToDerivedCast(Info, E, Result); | 
|  | 7994 |  | 
| Richard Smith | 7bd54ab | 2019-05-15 20:22:21 +0000 | [diff] [blame] | 7995 | case CK_Dynamic: | 
|  | 7996 | if (!Visit(E->getSubExpr())) | 
|  | 7997 | return false; | 
|  | 7998 | return HandleDynamicCast(Info, cast<ExplicitCastExpr>(E), Result); | 
|  | 7999 |  | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 8000 | case CK_NullToPointer: | 
| Richard Smith | 4051ff7 | 2012-04-08 08:02:07 +0000 | [diff] [blame] | 8001 | VisitIgnoredValue(E->getSubExpr()); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8002 | return ZeroInitialization(E); | 
| John McCall | e84af4e | 2010-11-13 01:35:44 +0000 | [diff] [blame] | 8003 |  | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 8004 | case CK_IntegralToPointer: { | 
| Richard Smith | 6d6ecc3 | 2011-12-12 12:46:16 +0000 | [diff] [blame] | 8005 | CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; | 
|  | 8006 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 8007 | APValue Value; | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 8008 | if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) | 
| Eli Friedman | 847a2bc | 2009-12-27 05:43:15 +0000 | [diff] [blame] | 8009 | break; | 
| Daniel Dunbar | ce39954 | 2009-02-20 18:22:23 +0000 | [diff] [blame] | 8010 |  | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 8011 | if (Value.isInt()) { | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 8012 | unsigned Size = Info.Ctx.getTypeSize(E->getType()); | 
|  | 8013 | uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue(); | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 8014 | Result.Base = (Expr*)nullptr; | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 8015 | Result.InvalidBase = false; | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 8016 | Result.Offset = CharUnits::fromQuantity(N); | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 8017 | Result.Designator.setInvalid(); | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 8018 | Result.IsNullPtr = false; | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 8019 | return true; | 
|  | 8020 | } else { | 
|  | 8021 | // Cast is of an lvalue, no need to change value. | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 8022 | Result.setFrom(Info.Ctx, Value); | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 8023 | return true; | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 8024 | } | 
|  | 8025 | } | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 8026 |  | 
|  | 8027 | case CK_ArrayToPointerDecay: { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8028 | if (SubExpr->isGLValue()) { | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 8029 | if (!evaluateLValue(SubExpr, Result)) | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8030 | return false; | 
|  | 8031 | } else { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 8032 | APValue &Value = Info.CurrentCall->createTemporary( | 
|  | 8033 | SubExpr, SubExpr->getType(), false, Result); | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 8034 | if (!EvaluateInPlace(Value, Info, Result, SubExpr)) | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8035 | return false; | 
|  | 8036 | } | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 8037 | // The result is a pointer to the first element of the array. | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 8038 | auto *AT = Info.Ctx.getAsArrayType(SubExpr->getType()); | 
|  | 8039 | if (auto *CAT = dyn_cast<ConstantArrayType>(AT)) | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 8040 | Result.addArray(Info, E, CAT); | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 8041 | else | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 8042 | Result.addUnsizedArray(Info, E, AT->getElementType()); | 
| Richard Smith | 96e0c10 | 2011-11-04 02:25:55 +0000 | [diff] [blame] | 8043 | return true; | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 8044 | } | 
| Richard Smith | dd78544 | 2011-10-31 20:57:44 +0000 | [diff] [blame] | 8045 |  | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 8046 | case CK_FunctionToPointerDecay: | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 8047 | return evaluateLValue(SubExpr, Result); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 8048 |  | 
|  | 8049 | case CK_LValueToRValue: { | 
|  | 8050 | LValue LVal; | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 8051 | if (!evaluateLValue(E->getSubExpr(), LVal)) | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 8052 | return false; | 
|  | 8053 |  | 
|  | 8054 | APValue RVal; | 
|  | 8055 | // Note, we use the subexpression's type in order to retain cv-qualifiers. | 
|  | 8056 | if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), | 
|  | 8057 | LVal, RVal)) | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 8058 | return InvalidBaseOK && | 
|  | 8059 | evaluateLValueAsAllocSize(Info, LVal.Base, Result); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 8060 | return Success(RVal, E); | 
|  | 8061 | } | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 8062 | } | 
|  | 8063 |  | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 8064 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 8065 | } | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 8066 |  | 
| Richard Smith | 6822bd7 | 2018-10-26 19:26:45 +0000 | [diff] [blame] | 8067 | static CharUnits GetAlignOfType(EvalInfo &Info, QualType T, | 
|  | 8068 | UnaryExprOrTypeTrait ExprKind) { | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8069 | // C++ [expr.alignof]p3: | 
|  | 8070 | //     When alignof is applied to a reference type, the result is the | 
|  | 8071 | //     alignment of the referenced type. | 
|  | 8072 | if (const ReferenceType *Ref = T->getAs<ReferenceType>()) | 
|  | 8073 | T = Ref->getPointeeType(); | 
|  | 8074 |  | 
| Roger Ferrer Ibanez | 3fa38a1 | 2017-03-08 14:00:44 +0000 | [diff] [blame] | 8075 | if (T.getQualifiers().hasUnaligned()) | 
|  | 8076 | return CharUnits::One(); | 
| Richard Smith | 6822bd7 | 2018-10-26 19:26:45 +0000 | [diff] [blame] | 8077 |  | 
|  | 8078 | const bool AlignOfReturnsPreferred = | 
|  | 8079 | Info.Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; | 
|  | 8080 |  | 
|  | 8081 | // __alignof is defined to return the preferred alignment. | 
|  | 8082 | // Before 8, clang returned the preferred alignment for alignof and _Alignof | 
|  | 8083 | // as well. | 
|  | 8084 | if (ExprKind == UETT_PreferredAlignOf || AlignOfReturnsPreferred) | 
|  | 8085 | return Info.Ctx.toCharUnitsFromBits( | 
|  | 8086 | Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); | 
|  | 8087 | // alignof and _Alignof are defined to return the ABI alignment. | 
|  | 8088 | else if (ExprKind == UETT_AlignOf) | 
|  | 8089 | return Info.Ctx.getTypeAlignInChars(T.getTypePtr()); | 
|  | 8090 | else | 
|  | 8091 | llvm_unreachable("GetAlignOfType on a non-alignment ExprKind"); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8092 | } | 
|  | 8093 |  | 
| Richard Smith | 6822bd7 | 2018-10-26 19:26:45 +0000 | [diff] [blame] | 8094 | static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E, | 
|  | 8095 | UnaryExprOrTypeTrait ExprKind) { | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8096 | E = E->IgnoreParens(); | 
|  | 8097 |  | 
|  | 8098 | // The kinds of expressions that we have special-case logic here for | 
|  | 8099 | // should be kept up to date with the special checks for those | 
|  | 8100 | // expressions in Sema. | 
|  | 8101 |  | 
|  | 8102 | // alignof decl is always accepted, even if it doesn't make sense: we default | 
|  | 8103 | // to 1 in those cases. | 
|  | 8104 | if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) | 
|  | 8105 | return Info.Ctx.getDeclAlign(DRE->getDecl(), | 
|  | 8106 | /*RefAsPointee*/true); | 
|  | 8107 |  | 
|  | 8108 | if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) | 
|  | 8109 | return Info.Ctx.getDeclAlign(ME->getMemberDecl(), | 
|  | 8110 | /*RefAsPointee*/true); | 
|  | 8111 |  | 
| Richard Smith | 6822bd7 | 2018-10-26 19:26:45 +0000 | [diff] [blame] | 8112 | return GetAlignOfType(Info, E->getType(), ExprKind); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8113 | } | 
|  | 8114 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 8115 | // To be clear: this happily visits unsupported builtins. Better name welcomed. | 
|  | 8116 | bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) { | 
|  | 8117 | if (ExprEvaluatorBaseTy::VisitCallExpr(E)) | 
|  | 8118 | return true; | 
|  | 8119 |  | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 8120 | if (!(InvalidBaseOK && getAllocSizeAttr(E))) | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 8121 | return false; | 
|  | 8122 |  | 
|  | 8123 | Result.setInvalid(E); | 
|  | 8124 | QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType(); | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 8125 | Result.addUnsizedArray(Info, E, PointeeTy); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 8126 | return true; | 
|  | 8127 | } | 
|  | 8128 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 8129 | bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8130 | if (IsStringLiteralCall(E)) | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 8131 | return Success(E); | 
| Eli Friedman | c69d454 | 2009-01-25 01:54:01 +0000 | [diff] [blame] | 8132 |  | 
| Richard Smith | 6328cbd | 2016-11-16 00:57:23 +0000 | [diff] [blame] | 8133 | if (unsigned BuiltinOp = E->getBuiltinCallee()) | 
|  | 8134 | return VisitBuiltinCallExpr(E, BuiltinOp); | 
|  | 8135 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 8136 | return visitNonBuiltinCallExpr(E); | 
| Richard Smith | 6328cbd | 2016-11-16 00:57:23 +0000 | [diff] [blame] | 8137 | } | 
|  | 8138 |  | 
|  | 8139 | bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, | 
|  | 8140 | unsigned BuiltinOp) { | 
|  | 8141 | switch (BuiltinOp) { | 
| Richard Smith | 6cbd65d | 2013-07-11 02:27:57 +0000 | [diff] [blame] | 8142 | case Builtin::BI__builtin_addressof: | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 8143 | return evaluateLValue(E->getArg(0), Result); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8144 | case Builtin::BI__builtin_assume_aligned: { | 
|  | 8145 | // We need to be very careful here because: if the pointer does not have the | 
|  | 8146 | // asserted alignment, then the behavior is undefined, and undefined | 
|  | 8147 | // behavior is non-constant. | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 8148 | if (!evaluatePointer(E->getArg(0), Result)) | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8149 | return false; | 
| Richard Smith | 6cbd65d | 2013-07-11 02:27:57 +0000 | [diff] [blame] | 8150 |  | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8151 | LValue OffsetResult(Result); | 
|  | 8152 | APSInt Alignment; | 
|  | 8153 | if (!EvaluateInteger(E->getArg(1), Alignment, Info)) | 
|  | 8154 | return false; | 
| Richard Smith | 642a236 | 2017-01-30 23:30:26 +0000 | [diff] [blame] | 8155 | CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue()); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8156 |  | 
|  | 8157 | if (E->getNumArgs() > 2) { | 
|  | 8158 | APSInt Offset; | 
|  | 8159 | if (!EvaluateInteger(E->getArg(2), Offset, Info)) | 
|  | 8160 | return false; | 
|  | 8161 |  | 
| Richard Smith | 642a236 | 2017-01-30 23:30:26 +0000 | [diff] [blame] | 8162 | int64_t AdditionalOffset = -Offset.getZExtValue(); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8163 | OffsetResult.Offset += CharUnits::fromQuantity(AdditionalOffset); | 
|  | 8164 | } | 
|  | 8165 |  | 
|  | 8166 | // If there is a base object, then it must have the correct alignment. | 
|  | 8167 | if (OffsetResult.Base) { | 
|  | 8168 | CharUnits BaseAlignment; | 
|  | 8169 | if (const ValueDecl *VD = | 
|  | 8170 | OffsetResult.Base.dyn_cast<const ValueDecl*>()) { | 
|  | 8171 | BaseAlignment = Info.Ctx.getDeclAlign(VD); | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 8172 | } else if (const Expr *E = OffsetResult.Base.dyn_cast<const Expr *>()) { | 
|  | 8173 | BaseAlignment = GetAlignOfExpr(Info, E, UETT_AlignOf); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8174 | } else { | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 8175 | BaseAlignment = GetAlignOfType( | 
|  | 8176 | Info, OffsetResult.Base.getTypeInfoType(), UETT_AlignOf); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8177 | } | 
|  | 8178 |  | 
|  | 8179 | if (BaseAlignment < Align) { | 
|  | 8180 | Result.Designator.setInvalid(); | 
| Richard Smith | 642a236 | 2017-01-30 23:30:26 +0000 | [diff] [blame] | 8181 | // FIXME: Add support to Diagnostic for long / long long. | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8182 | CCEDiag(E->getArg(0), | 
|  | 8183 | diag::note_constexpr_baa_insufficient_alignment) << 0 | 
| Richard Smith | 642a236 | 2017-01-30 23:30:26 +0000 | [diff] [blame] | 8184 | << (unsigned)BaseAlignment.getQuantity() | 
|  | 8185 | << (unsigned)Align.getQuantity(); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8186 | return false; | 
|  | 8187 | } | 
|  | 8188 | } | 
|  | 8189 |  | 
|  | 8190 | // The offset must also have the correct alignment. | 
| Rui Ueyama | 83aa979 | 2016-01-14 21:00:27 +0000 | [diff] [blame] | 8191 | if (OffsetResult.Offset.alignTo(Align) != OffsetResult.Offset) { | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8192 | Result.Designator.setInvalid(); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8193 |  | 
| Richard Smith | 642a236 | 2017-01-30 23:30:26 +0000 | [diff] [blame] | 8194 | (OffsetResult.Base | 
|  | 8195 | ? CCEDiag(E->getArg(0), | 
|  | 8196 | diag::note_constexpr_baa_insufficient_alignment) << 1 | 
|  | 8197 | : CCEDiag(E->getArg(0), | 
|  | 8198 | diag::note_constexpr_baa_value_insufficient_alignment)) | 
|  | 8199 | << (int)OffsetResult.Offset.getQuantity() | 
|  | 8200 | << (unsigned)Align.getQuantity(); | 
| Hal Finkel | 0dd05d4 | 2014-10-03 17:18:37 +0000 | [diff] [blame] | 8201 | return false; | 
|  | 8202 | } | 
|  | 8203 |  | 
|  | 8204 | return true; | 
|  | 8205 | } | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 8206 | case Builtin::BI__builtin_operator_new: | 
|  | 8207 | return HandleOperatorNewCall(Info, E, Result); | 
| Eric Fiselier | 2618750 | 2018-12-14 21:11:28 +0000 | [diff] [blame] | 8208 | case Builtin::BI__builtin_launder: | 
|  | 8209 | return evaluatePointer(E->getArg(0), Result); | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8210 | case Builtin::BIstrchr: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8211 | case Builtin::BIwcschr: | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8212 | case Builtin::BImemchr: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8213 | case Builtin::BIwmemchr: | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8214 | if (Info.getLangOpts().CPlusPlus11) | 
|  | 8215 | Info.CCEDiag(E, diag::note_constexpr_invalid_function) | 
|  | 8216 | << /*isConstexpr*/0 << /*isConstructor*/0 | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8217 | << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8218 | else | 
|  | 8219 | Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Adrian Prantl | f3b3ccd | 2017-12-19 22:06:11 +0000 | [diff] [blame] | 8220 | LLVM_FALLTHROUGH; | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8221 | case Builtin::BI__builtin_strchr: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8222 | case Builtin::BI__builtin_wcschr: | 
|  | 8223 | case Builtin::BI__builtin_memchr: | 
| Richard Smith | 5e29dd3 | 2017-01-20 00:45:35 +0000 | [diff] [blame] | 8224 | case Builtin::BI__builtin_char_memchr: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8225 | case Builtin::BI__builtin_wmemchr: { | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8226 | if (!Visit(E->getArg(0))) | 
|  | 8227 | return false; | 
|  | 8228 | APSInt Desired; | 
|  | 8229 | if (!EvaluateInteger(E->getArg(1), Desired, Info)) | 
|  | 8230 | return false; | 
|  | 8231 | uint64_t MaxLength = uint64_t(-1); | 
|  | 8232 | if (BuiltinOp != Builtin::BIstrchr && | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8233 | BuiltinOp != Builtin::BIwcschr && | 
|  | 8234 | BuiltinOp != Builtin::BI__builtin_strchr && | 
|  | 8235 | BuiltinOp != Builtin::BI__builtin_wcschr) { | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8236 | APSInt N; | 
|  | 8237 | if (!EvaluateInteger(E->getArg(2), N, Info)) | 
|  | 8238 | return false; | 
|  | 8239 | MaxLength = N.getExtValue(); | 
|  | 8240 | } | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 8241 | // We cannot find the value if there are no candidates to match against. | 
|  | 8242 | if (MaxLength == 0u) | 
|  | 8243 | return ZeroInitialization(E); | 
|  | 8244 | if (!Result.checkNullPointerForFoldAccess(Info, E, AK_Read) || | 
|  | 8245 | Result.Designator.Invalid) | 
|  | 8246 | return false; | 
|  | 8247 | QualType CharTy = Result.Designator.getType(Info.Ctx); | 
|  | 8248 | bool IsRawByte = BuiltinOp == Builtin::BImemchr || | 
|  | 8249 | BuiltinOp == Builtin::BI__builtin_memchr; | 
|  | 8250 | assert(IsRawByte || | 
|  | 8251 | Info.Ctx.hasSameUnqualifiedType( | 
|  | 8252 | CharTy, E->getArg(0)->getType()->getPointeeType())); | 
|  | 8253 | // Pointers to const void may point to objects of incomplete type. | 
|  | 8254 | if (IsRawByte && CharTy->isIncompleteType()) { | 
|  | 8255 | Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy; | 
|  | 8256 | return false; | 
|  | 8257 | } | 
|  | 8258 | // Give up on byte-oriented matching against multibyte elements. | 
|  | 8259 | // FIXME: We can compare the bytes in the correct order. | 
|  | 8260 | if (IsRawByte && Info.Ctx.getTypeSizeInChars(CharTy) != CharUnits::One()) | 
|  | 8261 | return false; | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8262 | // Figure out what value we're actually looking for (after converting to | 
|  | 8263 | // the corresponding unsigned type if necessary). | 
|  | 8264 | uint64_t DesiredVal; | 
|  | 8265 | bool StopAtNull = false; | 
|  | 8266 | switch (BuiltinOp) { | 
|  | 8267 | case Builtin::BIstrchr: | 
|  | 8268 | case Builtin::BI__builtin_strchr: | 
|  | 8269 | // strchr compares directly to the passed integer, and therefore | 
|  | 8270 | // always fails if given an int that is not a char. | 
|  | 8271 | if (!APSInt::isSameValue(HandleIntToIntCast(Info, E, CharTy, | 
|  | 8272 | E->getArg(1)->getType(), | 
|  | 8273 | Desired), | 
|  | 8274 | Desired)) | 
|  | 8275 | return ZeroInitialization(E); | 
|  | 8276 | StopAtNull = true; | 
| Adrian Prantl | f3b3ccd | 2017-12-19 22:06:11 +0000 | [diff] [blame] | 8277 | LLVM_FALLTHROUGH; | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8278 | case Builtin::BImemchr: | 
|  | 8279 | case Builtin::BI__builtin_memchr: | 
| Richard Smith | 5e29dd3 | 2017-01-20 00:45:35 +0000 | [diff] [blame] | 8280 | case Builtin::BI__builtin_char_memchr: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8281 | // memchr compares by converting both sides to unsigned char. That's also | 
|  | 8282 | // correct for strchr if we get this far (to cope with plain char being | 
|  | 8283 | // unsigned in the strchr case). | 
|  | 8284 | DesiredVal = Desired.trunc(Info.Ctx.getCharWidth()).getZExtValue(); | 
|  | 8285 | break; | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8286 |  | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8287 | case Builtin::BIwcschr: | 
|  | 8288 | case Builtin::BI__builtin_wcschr: | 
|  | 8289 | StopAtNull = true; | 
| Adrian Prantl | f3b3ccd | 2017-12-19 22:06:11 +0000 | [diff] [blame] | 8290 | LLVM_FALLTHROUGH; | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8291 | case Builtin::BIwmemchr: | 
|  | 8292 | case Builtin::BI__builtin_wmemchr: | 
|  | 8293 | // wcschr and wmemchr are given a wchar_t to look for. Just use it. | 
|  | 8294 | DesiredVal = Desired.getZExtValue(); | 
|  | 8295 | break; | 
|  | 8296 | } | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8297 |  | 
|  | 8298 | for (; MaxLength; --MaxLength) { | 
|  | 8299 | APValue Char; | 
|  | 8300 | if (!handleLValueToRValueConversion(Info, E, CharTy, Result, Char) || | 
|  | 8301 | !Char.isInt()) | 
|  | 8302 | return false; | 
|  | 8303 | if (Char.getInt().getZExtValue() == DesiredVal) | 
|  | 8304 | return true; | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 8305 | if (StopAtNull && !Char.getInt()) | 
| Richard Smith | e950795 | 2016-11-12 01:39:56 +0000 | [diff] [blame] | 8306 | break; | 
|  | 8307 | if (!HandleLValueArrayAdjustment(Info, E, Result, CharTy, 1)) | 
|  | 8308 | return false; | 
|  | 8309 | } | 
|  | 8310 | // Not found: return nullptr. | 
|  | 8311 | return ZeroInitialization(E); | 
|  | 8312 | } | 
|  | 8313 |  | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 8314 | case Builtin::BImemcpy: | 
|  | 8315 | case Builtin::BImemmove: | 
|  | 8316 | case Builtin::BIwmemcpy: | 
|  | 8317 | case Builtin::BIwmemmove: | 
|  | 8318 | if (Info.getLangOpts().CPlusPlus11) | 
|  | 8319 | Info.CCEDiag(E, diag::note_constexpr_invalid_function) | 
|  | 8320 | << /*isConstexpr*/0 << /*isConstructor*/0 | 
|  | 8321 | << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); | 
|  | 8322 | else | 
|  | 8323 | Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
|  | 8324 | LLVM_FALLTHROUGH; | 
|  | 8325 | case Builtin::BI__builtin_memcpy: | 
|  | 8326 | case Builtin::BI__builtin_memmove: | 
|  | 8327 | case Builtin::BI__builtin_wmemcpy: | 
|  | 8328 | case Builtin::BI__builtin_wmemmove: { | 
|  | 8329 | bool WChar = BuiltinOp == Builtin::BIwmemcpy || | 
|  | 8330 | BuiltinOp == Builtin::BIwmemmove || | 
|  | 8331 | BuiltinOp == Builtin::BI__builtin_wmemcpy || | 
|  | 8332 | BuiltinOp == Builtin::BI__builtin_wmemmove; | 
|  | 8333 | bool Move = BuiltinOp == Builtin::BImemmove || | 
|  | 8334 | BuiltinOp == Builtin::BIwmemmove || | 
|  | 8335 | BuiltinOp == Builtin::BI__builtin_memmove || | 
|  | 8336 | BuiltinOp == Builtin::BI__builtin_wmemmove; | 
|  | 8337 |  | 
|  | 8338 | // The result of mem* is the first argument. | 
| Richard Smith | 128719c | 2018-09-13 22:47:33 +0000 | [diff] [blame] | 8339 | if (!Visit(E->getArg(0))) | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 8340 | return false; | 
|  | 8341 | LValue Dest = Result; | 
|  | 8342 |  | 
|  | 8343 | LValue Src; | 
| Richard Smith | 128719c | 2018-09-13 22:47:33 +0000 | [diff] [blame] | 8344 | if (!EvaluatePointer(E->getArg(1), Src, Info)) | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 8345 | return false; | 
|  | 8346 |  | 
|  | 8347 | APSInt N; | 
|  | 8348 | if (!EvaluateInteger(E->getArg(2), N, Info)) | 
|  | 8349 | return false; | 
|  | 8350 | assert(!N.isSigned() && "memcpy and friends take an unsigned size"); | 
|  | 8351 |  | 
|  | 8352 | // If the size is zero, we treat this as always being a valid no-op. | 
|  | 8353 | // (Even if one of the src and dest pointers is null.) | 
|  | 8354 | if (!N) | 
|  | 8355 | return true; | 
|  | 8356 |  | 
| Richard Smith | 128719c | 2018-09-13 22:47:33 +0000 | [diff] [blame] | 8357 | // Otherwise, if either of the operands is null, we can't proceed. Don't | 
|  | 8358 | // try to determine the type of the copied objects, because there aren't | 
|  | 8359 | // any. | 
|  | 8360 | if (!Src.Base || !Dest.Base) { | 
|  | 8361 | APValue Val; | 
|  | 8362 | (!Src.Base ? Src : Dest).moveInto(Val); | 
|  | 8363 | Info.FFDiag(E, diag::note_constexpr_memcpy_null) | 
|  | 8364 | << Move << WChar << !!Src.Base | 
|  | 8365 | << Val.getAsString(Info.Ctx, E->getArg(0)->getType()); | 
|  | 8366 | return false; | 
|  | 8367 | } | 
|  | 8368 | if (Src.Designator.Invalid || Dest.Designator.Invalid) | 
|  | 8369 | return false; | 
|  | 8370 |  | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 8371 | // We require that Src and Dest are both pointers to arrays of | 
|  | 8372 | // trivially-copyable type. (For the wide version, the designator will be | 
|  | 8373 | // invalid if the designated object is not a wchar_t.) | 
|  | 8374 | QualType T = Dest.Designator.getType(Info.Ctx); | 
|  | 8375 | QualType SrcT = Src.Designator.getType(Info.Ctx); | 
|  | 8376 | if (!Info.Ctx.hasSameUnqualifiedType(T, SrcT)) { | 
|  | 8377 | Info.FFDiag(E, diag::note_constexpr_memcpy_type_pun) << Move << SrcT << T; | 
|  | 8378 | return false; | 
|  | 8379 | } | 
| Petr Pavlu | ed083f2 | 2018-10-04 09:25:44 +0000 | [diff] [blame] | 8380 | if (T->isIncompleteType()) { | 
|  | 8381 | Info.FFDiag(E, diag::note_constexpr_memcpy_incomplete_type) << Move << T; | 
|  | 8382 | return false; | 
|  | 8383 | } | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 8384 | if (!T.isTriviallyCopyableType(Info.Ctx)) { | 
|  | 8385 | Info.FFDiag(E, diag::note_constexpr_memcpy_nontrivial) << Move << T; | 
|  | 8386 | return false; | 
|  | 8387 | } | 
|  | 8388 |  | 
|  | 8389 | // Figure out how many T's we're copying. | 
|  | 8390 | uint64_t TSize = Info.Ctx.getTypeSizeInChars(T).getQuantity(); | 
|  | 8391 | if (!WChar) { | 
|  | 8392 | uint64_t Remainder; | 
|  | 8393 | llvm::APInt OrigN = N; | 
|  | 8394 | llvm::APInt::udivrem(OrigN, TSize, N, Remainder); | 
|  | 8395 | if (Remainder) { | 
|  | 8396 | Info.FFDiag(E, diag::note_constexpr_memcpy_unsupported) | 
|  | 8397 | << Move << WChar << 0 << T << OrigN.toString(10, /*Signed*/false) | 
|  | 8398 | << (unsigned)TSize; | 
|  | 8399 | return false; | 
|  | 8400 | } | 
|  | 8401 | } | 
|  | 8402 |  | 
|  | 8403 | // Check that the copying will remain within the arrays, just so that we | 
|  | 8404 | // can give a more meaningful diagnostic. This implicitly also checks that | 
|  | 8405 | // N fits into 64 bits. | 
|  | 8406 | uint64_t RemainingSrcSize = Src.Designator.validIndexAdjustments().second; | 
|  | 8407 | uint64_t RemainingDestSize = Dest.Designator.validIndexAdjustments().second; | 
|  | 8408 | if (N.ugt(RemainingSrcSize) || N.ugt(RemainingDestSize)) { | 
|  | 8409 | Info.FFDiag(E, diag::note_constexpr_memcpy_unsupported) | 
|  | 8410 | << Move << WChar << (N.ugt(RemainingSrcSize) ? 1 : 2) << T | 
|  | 8411 | << N.toString(10, /*Signed*/false); | 
|  | 8412 | return false; | 
|  | 8413 | } | 
|  | 8414 | uint64_t NElems = N.getZExtValue(); | 
|  | 8415 | uint64_t NBytes = NElems * TSize; | 
|  | 8416 |  | 
|  | 8417 | // Check for overlap. | 
|  | 8418 | int Direction = 1; | 
|  | 8419 | if (HasSameBase(Src, Dest)) { | 
|  | 8420 | uint64_t SrcOffset = Src.getLValueOffset().getQuantity(); | 
|  | 8421 | uint64_t DestOffset = Dest.getLValueOffset().getQuantity(); | 
|  | 8422 | if (DestOffset >= SrcOffset && DestOffset - SrcOffset < NBytes) { | 
|  | 8423 | // Dest is inside the source region. | 
|  | 8424 | if (!Move) { | 
|  | 8425 | Info.FFDiag(E, diag::note_constexpr_memcpy_overlap) << WChar; | 
|  | 8426 | return false; | 
|  | 8427 | } | 
|  | 8428 | // For memmove and friends, copy backwards. | 
|  | 8429 | if (!HandleLValueArrayAdjustment(Info, E, Src, T, NElems - 1) || | 
|  | 8430 | !HandleLValueArrayAdjustment(Info, E, Dest, T, NElems - 1)) | 
|  | 8431 | return false; | 
|  | 8432 | Direction = -1; | 
|  | 8433 | } else if (!Move && SrcOffset >= DestOffset && | 
|  | 8434 | SrcOffset - DestOffset < NBytes) { | 
|  | 8435 | // Src is inside the destination region for memcpy: invalid. | 
|  | 8436 | Info.FFDiag(E, diag::note_constexpr_memcpy_overlap) << WChar; | 
|  | 8437 | return false; | 
|  | 8438 | } | 
|  | 8439 | } | 
|  | 8440 |  | 
|  | 8441 | while (true) { | 
|  | 8442 | APValue Val; | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 8443 | // FIXME: Set WantObjectRepresentation to true if we're copying a | 
|  | 8444 | // char-like type? | 
| Richard Smith | 06f71b5 | 2018-08-04 00:57:17 +0000 | [diff] [blame] | 8445 | if (!handleLValueToRValueConversion(Info, E, T, Src, Val) || | 
|  | 8446 | !handleAssignment(Info, E, Dest, T, Val)) | 
|  | 8447 | return false; | 
|  | 8448 | // Do not iterate past the last element; if we're copying backwards, that | 
|  | 8449 | // might take us off the start of the array. | 
|  | 8450 | if (--NElems == 0) | 
|  | 8451 | return true; | 
|  | 8452 | if (!HandleLValueArrayAdjustment(Info, E, Src, T, Direction) || | 
|  | 8453 | !HandleLValueArrayAdjustment(Info, E, Dest, T, Direction)) | 
|  | 8454 | return false; | 
|  | 8455 | } | 
|  | 8456 | } | 
|  | 8457 |  | 
| Richard Smith | 6cbd65d | 2013-07-11 02:27:57 +0000 | [diff] [blame] | 8458 | default: | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 8459 | break; | 
| Richard Smith | 6cbd65d | 2013-07-11 02:27:57 +0000 | [diff] [blame] | 8460 | } | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 8461 |  | 
|  | 8462 | return visitNonBuiltinCallExpr(E); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 8463 | } | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 8464 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8465 | static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This, | 
|  | 8466 | APValue &Result, const InitListExpr *ILE, | 
|  | 8467 | QualType AllocType); | 
|  | 8468 |  | 
|  | 8469 | bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { | 
| Richard Smith | 62a9556 | 2019-09-27 01:26:49 +0000 | [diff] [blame] | 8470 | if (!Info.getLangOpts().CPlusPlus2a) | 
|  | 8471 | Info.CCEDiag(E, diag::note_constexpr_new); | 
|  | 8472 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8473 | // We cannot speculatively evaluate a delete expression. | 
|  | 8474 | if (Info.SpeculativeEvaluationDepth) | 
|  | 8475 | return false; | 
|  | 8476 |  | 
|  | 8477 | FunctionDecl *OperatorNew = E->getOperatorNew(); | 
| Richard Smith | b542602 | 2019-10-03 00:39:35 +0000 | [diff] [blame] | 8478 |  | 
|  | 8479 | bool IsNothrow = false; | 
|  | 8480 | bool IsPlacement = false; | 
|  | 8481 | if (OperatorNew->isReservedGlobalPlacementOperator() && | 
|  | 8482 | Info.CurrentCall->isStdFunction() && !E->isArray()) { | 
|  | 8483 | // FIXME Support array placement new. | 
|  | 8484 | assert(E->getNumPlacementArgs() == 1); | 
|  | 8485 | if (!EvaluatePointer(E->getPlacementArg(0), Result, Info)) | 
|  | 8486 | return false; | 
|  | 8487 | if (Result.Designator.Invalid) | 
|  | 8488 | return false; | 
|  | 8489 | IsPlacement = true; | 
|  | 8490 | } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8491 | Info.FFDiag(E, diag::note_constexpr_new_non_replaceable) | 
|  | 8492 | << isa<CXXMethodDecl>(OperatorNew) << OperatorNew; | 
|  | 8493 | return false; | 
| Richard Smith | b542602 | 2019-10-03 00:39:35 +0000 | [diff] [blame] | 8494 | } else if (E->getNumPlacementArgs()) { | 
| Richard Smith | 62a9556 | 2019-09-27 01:26:49 +0000 | [diff] [blame] | 8495 | // The only new-placement list we support is of the form (std::nothrow). | 
|  | 8496 | // | 
|  | 8497 | // FIXME: There is no restriction on this, but it's not clear that any | 
|  | 8498 | // other form makes any sense. We get here for cases such as: | 
|  | 8499 | // | 
|  | 8500 | //   new (std::align_val_t{N}) X(int) | 
|  | 8501 | // | 
|  | 8502 | // (which should presumably be valid only if N is a multiple of | 
|  | 8503 | // alignof(int), and in any case can't be deallocated unless N is | 
|  | 8504 | // alignof(X) and X has new-extended alignment). | 
|  | 8505 | if (E->getNumPlacementArgs() != 1 || | 
|  | 8506 | !E->getPlacementArg(0)->getType()->isNothrowT()) | 
|  | 8507 | return Error(E, diag::note_constexpr_new_placement); | 
|  | 8508 |  | 
|  | 8509 | LValue Nothrow; | 
|  | 8510 | if (!EvaluateLValue(E->getPlacementArg(0), Nothrow, Info)) | 
|  | 8511 | return false; | 
|  | 8512 | IsNothrow = true; | 
|  | 8513 | } | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8514 |  | 
|  | 8515 | const Expr *Init = E->getInitializer(); | 
|  | 8516 | const InitListExpr *ResizedArrayILE = nullptr; | 
|  | 8517 |  | 
|  | 8518 | QualType AllocType = E->getAllocatedType(); | 
|  | 8519 | if (Optional<const Expr*> ArraySize = E->getArraySize()) { | 
|  | 8520 | const Expr *Stripped = *ArraySize; | 
|  | 8521 | for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped); | 
|  | 8522 | Stripped = ICE->getSubExpr()) | 
|  | 8523 | if (ICE->getCastKind() != CK_NoOp && | 
|  | 8524 | ICE->getCastKind() != CK_IntegralCast) | 
|  | 8525 | break; | 
|  | 8526 |  | 
|  | 8527 | llvm::APSInt ArrayBound; | 
|  | 8528 | if (!EvaluateInteger(Stripped, ArrayBound, Info)) | 
|  | 8529 | return false; | 
|  | 8530 |  | 
|  | 8531 | // C++ [expr.new]p9: | 
|  | 8532 | //   The expression is erroneous if: | 
|  | 8533 | //   -- [...] its value before converting to size_t [or] applying the | 
|  | 8534 | //      second standard conversion sequence is less than zero | 
|  | 8535 | if (ArrayBound.isSigned() && ArrayBound.isNegative()) { | 
| Richard Smith | 62a9556 | 2019-09-27 01:26:49 +0000 | [diff] [blame] | 8536 | if (IsNothrow) | 
|  | 8537 | return ZeroInitialization(E); | 
|  | 8538 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8539 | Info.FFDiag(*ArraySize, diag::note_constexpr_new_negative) | 
|  | 8540 | << ArrayBound << (*ArraySize)->getSourceRange(); | 
|  | 8541 | return false; | 
|  | 8542 | } | 
|  | 8543 |  | 
|  | 8544 | //   -- its value is such that the size of the allocated object would | 
|  | 8545 | //      exceed the implementation-defined limit | 
|  | 8546 | if (ConstantArrayType::getNumAddressingBits(Info.Ctx, AllocType, | 
|  | 8547 | ArrayBound) > | 
|  | 8548 | ConstantArrayType::getMaxSizeBits(Info.Ctx)) { | 
| Richard Smith | 62a9556 | 2019-09-27 01:26:49 +0000 | [diff] [blame] | 8549 | if (IsNothrow) | 
|  | 8550 | return ZeroInitialization(E); | 
|  | 8551 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8552 | Info.FFDiag(*ArraySize, diag::note_constexpr_new_too_large) | 
|  | 8553 | << ArrayBound << (*ArraySize)->getSourceRange(); | 
|  | 8554 | return false; | 
|  | 8555 | } | 
|  | 8556 |  | 
|  | 8557 | //   -- the new-initializer is a braced-init-list and the number of | 
|  | 8558 | //      array elements for which initializers are provided [...] | 
|  | 8559 | //      exceeds the number of elements to initialize | 
|  | 8560 | if (Init) { | 
|  | 8561 | auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType()); | 
|  | 8562 | assert(CAT && "unexpected type for array initializer"); | 
|  | 8563 |  | 
|  | 8564 | unsigned Bits = | 
|  | 8565 | std::max(CAT->getSize().getBitWidth(), ArrayBound.getBitWidth()); | 
|  | 8566 | llvm::APInt InitBound = CAT->getSize().zextOrSelf(Bits); | 
|  | 8567 | llvm::APInt AllocBound = ArrayBound.zextOrSelf(Bits); | 
|  | 8568 | if (InitBound.ugt(AllocBound)) { | 
| Richard Smith | 62a9556 | 2019-09-27 01:26:49 +0000 | [diff] [blame] | 8569 | if (IsNothrow) | 
|  | 8570 | return ZeroInitialization(E); | 
|  | 8571 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8572 | Info.FFDiag(*ArraySize, diag::note_constexpr_new_too_small) | 
|  | 8573 | << AllocBound.toString(10, /*Signed=*/false) | 
|  | 8574 | << InitBound.toString(10, /*Signed=*/false) | 
|  | 8575 | << (*ArraySize)->getSourceRange(); | 
|  | 8576 | return false; | 
|  | 8577 | } | 
|  | 8578 |  | 
|  | 8579 | // If the sizes differ, we must have an initializer list, and we need | 
|  | 8580 | // special handling for this case when we initialize. | 
|  | 8581 | if (InitBound != AllocBound) | 
|  | 8582 | ResizedArrayILE = cast<InitListExpr>(Init); | 
|  | 8583 | } | 
|  | 8584 |  | 
| Richard Smith | 772e266 | 2019-10-04 01:25:59 +0000 | [diff] [blame] | 8585 | AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound, nullptr, | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8586 | ArrayType::Normal, 0); | 
|  | 8587 | } else { | 
|  | 8588 | assert(!AllocType->isArrayType() && | 
|  | 8589 | "array allocation with non-array new"); | 
|  | 8590 | } | 
|  | 8591 |  | 
| Richard Smith | b542602 | 2019-10-03 00:39:35 +0000 | [diff] [blame] | 8592 | APValue *Val; | 
|  | 8593 | if (IsPlacement) { | 
|  | 8594 | AccessKinds AK = AK_Construct; | 
|  | 8595 | struct FindObjectHandler { | 
|  | 8596 | EvalInfo &Info; | 
|  | 8597 | const Expr *E; | 
|  | 8598 | QualType AllocType; | 
|  | 8599 | const AccessKinds AccessKind; | 
|  | 8600 | APValue *Value; | 
|  | 8601 |  | 
|  | 8602 | typedef bool result_type; | 
|  | 8603 | bool failed() { return false; } | 
|  | 8604 | bool found(APValue &Subobj, QualType SubobjType) { | 
|  | 8605 | // FIXME: Reject the cases where [basic.life]p8 would not permit the | 
|  | 8606 | // old name of the object to be used to name the new object. | 
|  | 8607 | if (!Info.Ctx.hasSameUnqualifiedType(SubobjType, AllocType)) { | 
|  | 8608 | Info.FFDiag(E, diag::note_constexpr_placement_new_wrong_type) << | 
|  | 8609 | SubobjType << AllocType; | 
|  | 8610 | return false; | 
|  | 8611 | } | 
|  | 8612 | Value = &Subobj; | 
|  | 8613 | return true; | 
|  | 8614 | } | 
|  | 8615 | bool found(APSInt &Value, QualType SubobjType) { | 
|  | 8616 | Info.FFDiag(E, diag::note_constexpr_construct_complex_elem); | 
|  | 8617 | return false; | 
|  | 8618 | } | 
|  | 8619 | bool found(APFloat &Value, QualType SubobjType) { | 
|  | 8620 | Info.FFDiag(E, diag::note_constexpr_construct_complex_elem); | 
|  | 8621 | return false; | 
|  | 8622 | } | 
|  | 8623 | } Handler = {Info, E, AllocType, AK, nullptr}; | 
|  | 8624 |  | 
|  | 8625 | CompleteObject Obj = findCompleteObject(Info, E, AK, Result, AllocType); | 
|  | 8626 | if (!Obj || !findSubobject(Info, E, Obj, Result.Designator, Handler)) | 
|  | 8627 | return false; | 
|  | 8628 |  | 
|  | 8629 | Val = Handler.Value; | 
|  | 8630 |  | 
|  | 8631 | // [basic.life]p1: | 
|  | 8632 | //   The lifetime of an object o of type T ends when [...] the storage | 
|  | 8633 | //   which the object occupies is [...] reused by an object that is not | 
|  | 8634 | //   nested within o (6.6.2). | 
|  | 8635 | *Val = APValue(); | 
|  | 8636 | } else { | 
|  | 8637 | // Perform the allocation and obtain a pointer to the resulting object. | 
|  | 8638 | Val = Info.createHeapAlloc(E, AllocType, Result); | 
|  | 8639 | if (!Val) | 
|  | 8640 | return false; | 
|  | 8641 | } | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 8642 |  | 
|  | 8643 | if (ResizedArrayILE) { | 
|  | 8644 | if (!EvaluateArrayNewInitList(Info, Result, *Val, ResizedArrayILE, | 
|  | 8645 | AllocType)) | 
|  | 8646 | return false; | 
|  | 8647 | } else if (Init) { | 
|  | 8648 | if (!EvaluateInPlace(*Val, Info, Result, Init)) | 
|  | 8649 | return false; | 
|  | 8650 | } else { | 
|  | 8651 | *Val = getDefaultInitValue(AllocType); | 
|  | 8652 | } | 
|  | 8653 |  | 
|  | 8654 | // Array new returns a pointer to the first element, not a pointer to the | 
|  | 8655 | // array. | 
|  | 8656 | if (auto *AT = AllocType->getAsArrayTypeUnsafe()) | 
|  | 8657 | Result.addArray(Info, E, cast<ConstantArrayType>(AT)); | 
|  | 8658 |  | 
|  | 8659 | return true; | 
|  | 8660 | } | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 8661 | //===----------------------------------------------------------------------===// | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8662 | // Member Pointer Evaluation | 
|  | 8663 | //===----------------------------------------------------------------------===// | 
|  | 8664 |  | 
|  | 8665 | namespace { | 
|  | 8666 | class MemberPointerExprEvaluator | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 8667 | : public ExprEvaluatorBase<MemberPointerExprEvaluator> { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8668 | MemberPtr &Result; | 
|  | 8669 |  | 
|  | 8670 | bool Success(const ValueDecl *D) { | 
|  | 8671 | Result = MemberPtr(D); | 
|  | 8672 | return true; | 
|  | 8673 | } | 
|  | 8674 | public: | 
|  | 8675 |  | 
|  | 8676 | MemberPointerExprEvaluator(EvalInfo &Info, MemberPtr &Result) | 
|  | 8677 | : ExprEvaluatorBaseTy(Info), Result(Result) {} | 
|  | 8678 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 8679 | bool Success(const APValue &V, const Expr *E) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8680 | Result.setFrom(V); | 
|  | 8681 | return true; | 
|  | 8682 | } | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8683 | bool ZeroInitialization(const Expr *E) { | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 8684 | return Success((const ValueDecl*)nullptr); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8685 | } | 
|  | 8686 |  | 
|  | 8687 | bool VisitCastExpr(const CastExpr *E); | 
|  | 8688 | bool VisitUnaryAddrOf(const UnaryOperator *E); | 
|  | 8689 | }; | 
|  | 8690 | } // end anonymous namespace | 
|  | 8691 |  | 
|  | 8692 | static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, | 
|  | 8693 | EvalInfo &Info) { | 
|  | 8694 | assert(E->isRValue() && E->getType()->isMemberPointerType()); | 
|  | 8695 | return MemberPointerExprEvaluator(Info, Result).Visit(E); | 
|  | 8696 | } | 
|  | 8697 |  | 
|  | 8698 | bool MemberPointerExprEvaluator::VisitCastExpr(const CastExpr *E) { | 
|  | 8699 | switch (E->getCastKind()) { | 
|  | 8700 | default: | 
|  | 8701 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
|  | 8702 |  | 
|  | 8703 | case CK_NullToMemberPointer: | 
| Richard Smith | 4051ff7 | 2012-04-08 08:02:07 +0000 | [diff] [blame] | 8704 | VisitIgnoredValue(E->getSubExpr()); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8705 | return ZeroInitialization(E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8706 |  | 
|  | 8707 | case CK_BaseToDerivedMemberPointer: { | 
|  | 8708 | if (!Visit(E->getSubExpr())) | 
|  | 8709 | return false; | 
|  | 8710 | if (E->path_empty()) | 
|  | 8711 | return true; | 
|  | 8712 | // Base-to-derived member pointer casts store the path in derived-to-base | 
|  | 8713 | // order, so iterate backwards. The CXXBaseSpecifier also provides us with | 
|  | 8714 | // the wrong end of the derived->base arc, so stagger the path by one class. | 
|  | 8715 | typedef std::reverse_iterator<CastExpr::path_const_iterator> ReverseIter; | 
|  | 8716 | for (ReverseIter PathI(E->path_end() - 1), PathE(E->path_begin()); | 
|  | 8717 | PathI != PathE; ++PathI) { | 
|  | 8718 | assert(!(*PathI)->isVirtual() && "memptr cast through vbase"); | 
|  | 8719 | const CXXRecordDecl *Derived = (*PathI)->getType()->getAsCXXRecordDecl(); | 
|  | 8720 | if (!Result.castToDerived(Derived)) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 8721 | return Error(E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8722 | } | 
|  | 8723 | const Type *FinalTy = E->getType()->castAs<MemberPointerType>()->getClass(); | 
|  | 8724 | if (!Result.castToDerived(FinalTy->getAsCXXRecordDecl())) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 8725 | return Error(E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8726 | return true; | 
|  | 8727 | } | 
|  | 8728 |  | 
|  | 8729 | case CK_DerivedToBaseMemberPointer: | 
|  | 8730 | if (!Visit(E->getSubExpr())) | 
|  | 8731 | return false; | 
|  | 8732 | for (CastExpr::path_const_iterator PathI = E->path_begin(), | 
|  | 8733 | PathE = E->path_end(); PathI != PathE; ++PathI) { | 
|  | 8734 | assert(!(*PathI)->isVirtual() && "memptr cast through vbase"); | 
|  | 8735 | const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl(); | 
|  | 8736 | if (!Result.castToBase(Base)) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 8737 | return Error(E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 8738 | } | 
|  | 8739 | return true; | 
|  | 8740 | } | 
|  | 8741 | } | 
|  | 8742 |  | 
|  | 8743 | bool MemberPointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { | 
|  | 8744 | // C++11 [expr.unary.op]p3 has very strict rules on how the address of a | 
|  | 8745 | // member can be formed. | 
|  | 8746 | return Success(cast<DeclRefExpr>(E->getSubExpr())->getDecl()); | 
|  | 8747 | } | 
|  | 8748 |  | 
|  | 8749 | //===----------------------------------------------------------------------===// | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8750 | // Record Evaluation | 
|  | 8751 | //===----------------------------------------------------------------------===// | 
|  | 8752 |  | 
|  | 8753 | namespace { | 
|  | 8754 | class RecordExprEvaluator | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 8755 | : public ExprEvaluatorBase<RecordExprEvaluator> { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8756 | const LValue &This; | 
|  | 8757 | APValue &Result; | 
|  | 8758 | public: | 
|  | 8759 |  | 
|  | 8760 | RecordExprEvaluator(EvalInfo &info, const LValue &This, APValue &Result) | 
|  | 8761 | : ExprEvaluatorBaseTy(info), This(This), Result(Result) {} | 
|  | 8762 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 8763 | bool Success(const APValue &V, const Expr *E) { | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 8764 | Result = V; | 
|  | 8765 | return true; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8766 | } | 
| Richard Smith | b8348f5 | 2016-05-12 22:16:28 +0000 | [diff] [blame] | 8767 | bool ZeroInitialization(const Expr *E) { | 
|  | 8768 | return ZeroInitialization(E, E->getType()); | 
|  | 8769 | } | 
|  | 8770 | bool ZeroInitialization(const Expr *E, QualType T); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8771 |  | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 8772 | bool VisitCallExpr(const CallExpr *E) { | 
|  | 8773 | return handleCallExpr(E, Result, &This); | 
|  | 8774 | } | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 8775 | bool VisitCastExpr(const CastExpr *E); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8776 | bool VisitInitListExpr(const InitListExpr *E); | 
| Richard Smith | b8348f5 | 2016-05-12 22:16:28 +0000 | [diff] [blame] | 8777 | bool VisitCXXConstructExpr(const CXXConstructExpr *E) { | 
|  | 8778 | return VisitCXXConstructExpr(E, E->getType()); | 
|  | 8779 | } | 
| Faisal Vali | c72a08c | 2017-01-09 03:02:53 +0000 | [diff] [blame] | 8780 | bool VisitLambdaExpr(const LambdaExpr *E); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 8781 | bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); | 
| Richard Smith | b8348f5 | 2016-05-12 22:16:28 +0000 | [diff] [blame] | 8782 | bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T); | 
| Richard Smith | cc1b96d | 2013-06-12 22:31:48 +0000 | [diff] [blame] | 8783 | bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 8784 | bool VisitBinCmp(const BinaryOperator *E); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8785 | }; | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 8786 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8787 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8788 | /// Perform zero-initialization on an object of non-union class type. | 
|  | 8789 | /// C++11 [dcl.init]p5: | 
|  | 8790 | ///  To zero-initialize an object or reference of type T means: | 
|  | 8791 | ///    [...] | 
|  | 8792 | ///    -- if T is a (possibly cv-qualified) non-union class type, | 
|  | 8793 | ///       each non-static data member and each base-class subobject is | 
|  | 8794 | ///       zero-initialized | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 8795 | static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, | 
|  | 8796 | const RecordDecl *RD, | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8797 | const LValue &This, APValue &Result) { | 
|  | 8798 | assert(!RD->isUnion() && "Expected non-union class type"); | 
|  | 8799 | const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD); | 
|  | 8800 | Result = APValue(APValue::UninitStruct(), CD ? CD->getNumBases() : 0, | 
| Aaron Ballman | 62e47c4 | 2014-03-10 13:43:55 +0000 | [diff] [blame] | 8801 | std::distance(RD->field_begin(), RD->field_end())); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8802 |  | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 8803 | if (RD->isInvalidDecl()) return false; | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8804 | const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); | 
|  | 8805 |  | 
|  | 8806 | if (CD) { | 
|  | 8807 | unsigned Index = 0; | 
|  | 8808 | for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(), | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 8809 | End = CD->bases_end(); I != End; ++I, ++Index) { | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8810 | const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl(); | 
|  | 8811 | LValue Subobject = This; | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 8812 | if (!HandleLValueDirectBase(Info, E, Subobject, CD, Base, &Layout)) | 
|  | 8813 | return false; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 8814 | if (!HandleClassZeroInitialization(Info, E, Base, Subobject, | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8815 | Result.getStructBase(Index))) | 
|  | 8816 | return false; | 
|  | 8817 | } | 
|  | 8818 | } | 
|  | 8819 |  | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 8820 | for (const auto *I : RD->fields()) { | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8821 | // -- if T is a reference type, no initialization is performed. | 
| David Blaikie | 2d7c57e | 2012-04-30 02:36:29 +0000 | [diff] [blame] | 8822 | if (I->getType()->isReferenceType()) | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8823 | continue; | 
|  | 8824 |  | 
|  | 8825 | LValue Subobject = This; | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 8826 | if (!HandleLValueMember(Info, E, Subobject, I, &Layout)) | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 8827 | return false; | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8828 |  | 
| David Blaikie | 2d7c57e | 2012-04-30 02:36:29 +0000 | [diff] [blame] | 8829 | ImplicitValueInitExpr VIE(I->getType()); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 8830 | if (!EvaluateInPlace( | 
| David Blaikie | 2d7c57e | 2012-04-30 02:36:29 +0000 | [diff] [blame] | 8831 | Result.getStructField(I->getFieldIndex()), Info, Subobject, &VIE)) | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8832 | return false; | 
|  | 8833 | } | 
|  | 8834 |  | 
|  | 8835 | return true; | 
|  | 8836 | } | 
|  | 8837 |  | 
| Richard Smith | b8348f5 | 2016-05-12 22:16:28 +0000 | [diff] [blame] | 8838 | bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) { | 
|  | 8839 | const RecordDecl *RD = T->castAs<RecordType>()->getDecl(); | 
| John McCall | 3c79d88 | 2012-04-26 18:10:01 +0000 | [diff] [blame] | 8840 | if (RD->isInvalidDecl()) return false; | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8841 | if (RD->isUnion()) { | 
|  | 8842 | // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the | 
|  | 8843 | // object's first non-static named data member is zero-initialized | 
|  | 8844 | RecordDecl::field_iterator I = RD->field_begin(); | 
|  | 8845 | if (I == RD->field_end()) { | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 8846 | Result = APValue((const FieldDecl*)nullptr); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8847 | return true; | 
|  | 8848 | } | 
|  | 8849 |  | 
|  | 8850 | LValue Subobject = This; | 
| David Blaikie | 40ed297 | 2012-06-06 20:45:41 +0000 | [diff] [blame] | 8851 | if (!HandleLValueMember(Info, E, Subobject, *I)) | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 8852 | return false; | 
| David Blaikie | 40ed297 | 2012-06-06 20:45:41 +0000 | [diff] [blame] | 8853 | Result = APValue(*I); | 
| David Blaikie | 2d7c57e | 2012-04-30 02:36:29 +0000 | [diff] [blame] | 8854 | ImplicitValueInitExpr VIE(I->getType()); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 8855 | return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, &VIE); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8856 | } | 
|  | 8857 |  | 
| Richard Smith | 5d10860 | 2012-02-17 00:44:16 +0000 | [diff] [blame] | 8858 | if (isa<CXXRecordDecl>(RD) && cast<CXXRecordDecl>(RD)->getNumVBases()) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 8859 | Info.FFDiag(E, diag::note_constexpr_virtual_base) << RD; | 
| Richard Smith | 5d10860 | 2012-02-17 00:44:16 +0000 | [diff] [blame] | 8860 | return false; | 
|  | 8861 | } | 
|  | 8862 |  | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 8863 | return HandleClassZeroInitialization(Info, E, RD, This, Result); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 8864 | } | 
|  | 8865 |  | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 8866 | bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) { | 
|  | 8867 | switch (E->getCastKind()) { | 
|  | 8868 | default: | 
|  | 8869 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
|  | 8870 |  | 
|  | 8871 | case CK_ConstructorConversion: | 
|  | 8872 | return Visit(E->getSubExpr()); | 
|  | 8873 |  | 
|  | 8874 | case CK_DerivedToBase: | 
|  | 8875 | case CK_UncheckedDerivedToBase: { | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 8876 | APValue DerivedObject; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 8877 | if (!Evaluate(DerivedObject, Info, E->getSubExpr())) | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 8878 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 8879 | if (!DerivedObject.isStruct()) | 
|  | 8880 | return Error(E->getSubExpr()); | 
| Richard Smith | e97cbd7 | 2011-11-11 04:05:33 +0000 | [diff] [blame] | 8881 |  | 
|  | 8882 | // Derived-to-base rvalue conversion: just slice off the derived part. | 
|  | 8883 | APValue *Value = &DerivedObject; | 
|  | 8884 | const CXXRecordDecl *RD = E->getSubExpr()->getType()->getAsCXXRecordDecl(); | 
|  | 8885 | for (CastExpr::path_const_iterator PathI = E->path_begin(), | 
|  | 8886 | PathE = E->path_end(); PathI != PathE; ++PathI) { | 
|  | 8887 | assert(!(*PathI)->isVirtual() && "record rvalue with virtual base"); | 
|  | 8888 | const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl(); | 
|  | 8889 | Value = &Value->getStructBase(getBaseIndex(RD, Base)); | 
|  | 8890 | RD = Base; | 
|  | 8891 | } | 
|  | 8892 | Result = *Value; | 
|  | 8893 | return true; | 
|  | 8894 | } | 
|  | 8895 | } | 
|  | 8896 | } | 
|  | 8897 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8898 | bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { | 
| Richard Smith | 122f88d | 2016-12-06 23:52:28 +0000 | [diff] [blame] | 8899 | if (E->isTransparent()) | 
|  | 8900 | return Visit(E->getInit(0)); | 
|  | 8901 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8902 | const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl(); | 
| John McCall | 3c79d88 | 2012-04-26 18:10:01 +0000 | [diff] [blame] | 8903 | if (RD->isInvalidDecl()) return false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8904 | const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 8905 | auto *CXXRD = dyn_cast<CXXRecordDecl>(RD); | 
|  | 8906 |  | 
|  | 8907 | EvalInfo::EvaluatingConstructorRAII EvalObj( | 
|  | 8908 | Info, | 
|  | 8909 | ObjectUnderConstruction{This.getLValueBase(), This.Designator.Entries}, | 
|  | 8910 | CXXRD && CXXRD->getNumBases()); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8911 |  | 
|  | 8912 | if (RD->isUnion()) { | 
| Richard Smith | 9eae723 | 2012-01-12 18:54:33 +0000 | [diff] [blame] | 8913 | const FieldDecl *Field = E->getInitializedFieldInUnion(); | 
|  | 8914 | Result = APValue(Field); | 
|  | 8915 | if (!Field) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8916 | return true; | 
| Richard Smith | 9eae723 | 2012-01-12 18:54:33 +0000 | [diff] [blame] | 8917 |  | 
|  | 8918 | // If the initializer list for a union does not contain any elements, the | 
|  | 8919 | // first element of the union is value-initialized. | 
| Richard Smith | 852c9db | 2013-04-20 22:23:05 +0000 | [diff] [blame] | 8920 | // FIXME: The element should be initialized from an initializer list. | 
|  | 8921 | //        Is this difference ever observable for initializer lists which | 
|  | 8922 | //        we don't build? | 
| Richard Smith | 9eae723 | 2012-01-12 18:54:33 +0000 | [diff] [blame] | 8923 | ImplicitValueInitExpr VIE(Field->getType()); | 
|  | 8924 | const Expr *InitExpr = E->getNumInits() ? E->getInit(0) : &VIE; | 
|  | 8925 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8926 | LValue Subobject = This; | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 8927 | if (!HandleLValueMember(Info, InitExpr, Subobject, Field, &Layout)) | 
|  | 8928 | return false; | 
| Richard Smith | 852c9db | 2013-04-20 22:23:05 +0000 | [diff] [blame] | 8929 |  | 
|  | 8930 | // Temporarily override This, in case there's a CXXDefaultInitExpr in here. | 
|  | 8931 | ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, | 
|  | 8932 | isa<CXXDefaultInitExpr>(InitExpr)); | 
|  | 8933 |  | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 8934 | return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8935 | } | 
|  | 8936 |  | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 8937 | if (!Result.hasValue()) | 
| Richard Smith | c0d04a2 | 2016-05-25 22:06:25 +0000 | [diff] [blame] | 8938 | Result = APValue(APValue::UninitStruct(), CXXRD ? CXXRD->getNumBases() : 0, | 
|  | 8939 | std::distance(RD->field_begin(), RD->field_end())); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8940 | unsigned ElementNo = 0; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 8941 | bool Success = true; | 
| Richard Smith | 872307e | 2016-03-08 22:17:41 +0000 | [diff] [blame] | 8942 |  | 
|  | 8943 | // Initialize base classes. | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 8944 | if (CXXRD && CXXRD->getNumBases()) { | 
| Richard Smith | 872307e | 2016-03-08 22:17:41 +0000 | [diff] [blame] | 8945 | for (const auto &Base : CXXRD->bases()) { | 
|  | 8946 | assert(ElementNo < E->getNumInits() && "missing init for base class"); | 
|  | 8947 | const Expr *Init = E->getInit(ElementNo); | 
|  | 8948 |  | 
|  | 8949 | LValue Subobject = This; | 
|  | 8950 | if (!HandleLValueBase(Info, Init, Subobject, CXXRD, &Base)) | 
|  | 8951 | return false; | 
|  | 8952 |  | 
|  | 8953 | APValue &FieldVal = Result.getStructBase(ElementNo); | 
|  | 8954 | if (!EvaluateInPlace(FieldVal, Info, Subobject, Init)) { | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 8955 | if (!Info.noteFailure()) | 
| Richard Smith | 872307e | 2016-03-08 22:17:41 +0000 | [diff] [blame] | 8956 | return false; | 
|  | 8957 | Success = false; | 
|  | 8958 | } | 
|  | 8959 | ++ElementNo; | 
|  | 8960 | } | 
| Richard Smith | d3d6f4f | 2019-05-12 08:57:59 +0000 | [diff] [blame] | 8961 |  | 
|  | 8962 | EvalObj.finishedConstructingBases(); | 
| Richard Smith | 872307e | 2016-03-08 22:17:41 +0000 | [diff] [blame] | 8963 | } | 
|  | 8964 |  | 
|  | 8965 | // Initialize members. | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 8966 | for (const auto *Field : RD->fields()) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8967 | // Anonymous bit-fields are not considered members of the class for | 
|  | 8968 | // purposes of aggregate initialization. | 
|  | 8969 | if (Field->isUnnamedBitfield()) | 
|  | 8970 | continue; | 
|  | 8971 |  | 
|  | 8972 | LValue Subobject = This; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8973 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 8974 | bool HaveInit = ElementNo < E->getNumInits(); | 
|  | 8975 |  | 
|  | 8976 | // FIXME: Diagnostics here should point to the end of the initializer | 
|  | 8977 | // list, not the start. | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 8978 | if (!HandleLValueMember(Info, HaveInit ? E->getInit(ElementNo) : E, | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 8979 | Subobject, Field, &Layout)) | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 8980 | return false; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 8981 |  | 
|  | 8982 | // Perform an implicit value-initialization for members beyond the end of | 
|  | 8983 | // the initializer list. | 
|  | 8984 | ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType()); | 
| Richard Smith | 852c9db | 2013-04-20 22:23:05 +0000 | [diff] [blame] | 8985 | const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 8986 |  | 
| Richard Smith | 852c9db | 2013-04-20 22:23:05 +0000 | [diff] [blame] | 8987 | // Temporarily override This, in case there's a CXXDefaultInitExpr in here. | 
|  | 8988 | ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, | 
|  | 8989 | isa<CXXDefaultInitExpr>(Init)); | 
|  | 8990 |  | 
| Richard Smith | 49ca8aa | 2013-08-06 07:09:20 +0000 | [diff] [blame] | 8991 | APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); | 
|  | 8992 | if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || | 
|  | 8993 | (Field->isBitField() && !truncateBitfieldValue(Info, Init, | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 8994 | FieldVal, Field))) { | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 8995 | if (!Info.noteFailure()) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8996 | return false; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 8997 | Success = false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 8998 | } | 
|  | 8999 | } | 
|  | 9000 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 9001 | return Success; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9002 | } | 
|  | 9003 |  | 
| Richard Smith | b8348f5 | 2016-05-12 22:16:28 +0000 | [diff] [blame] | 9004 | bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, | 
|  | 9005 | QualType T) { | 
|  | 9006 | // Note that E's type is not necessarily the type of our class here; we might | 
|  | 9007 | // be initializing an array element instead. | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9008 | const CXXConstructorDecl *FD = E->getConstructor(); | 
| John McCall | 3c79d88 | 2012-04-26 18:10:01 +0000 | [diff] [blame] | 9009 | if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) return false; | 
|  | 9010 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9011 | bool ZeroInit = E->requiresZeroInitialization(); | 
|  | 9012 | if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { | 
| Richard Smith | 9eae723 | 2012-01-12 18:54:33 +0000 | [diff] [blame] | 9013 | // If we've already performed zero-initialization, we're already done. | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 9014 | if (Result.hasValue()) | 
| Richard Smith | 9eae723 | 2012-01-12 18:54:33 +0000 | [diff] [blame] | 9015 | return true; | 
|  | 9016 |  | 
| Richard Smith | c667cdc | 2019-09-18 17:37:44 +0000 | [diff] [blame] | 9017 | if (ZeroInit) | 
|  | 9018 | return ZeroInitialization(E, T); | 
|  | 9019 |  | 
|  | 9020 | Result = getDefaultInitValue(T); | 
|  | 9021 | return true; | 
| Richard Smith | cc36f69 | 2011-12-22 02:22:31 +0000 | [diff] [blame] | 9022 | } | 
|  | 9023 |  | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 9024 | const FunctionDecl *Definition = nullptr; | 
| Olivier Goffart | 8bc0caa2e | 2016-02-12 12:34:44 +0000 | [diff] [blame] | 9025 | auto Body = FD->getBody(Definition); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9026 |  | 
| Olivier Goffart | 8bc0caa2e | 2016-02-12 12:34:44 +0000 | [diff] [blame] | 9027 | if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 9028 | return false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9029 |  | 
| Richard Smith | 1bc5c2c | 2012-01-10 04:32:03 +0000 | [diff] [blame] | 9030 | // Avoid materializing a temporary for an elidable copy/move constructor. | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9031 | if (E->isElidable() && !ZeroInit) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9032 | if (const MaterializeTemporaryExpr *ME | 
|  | 9033 | = dyn_cast<MaterializeTemporaryExpr>(E->getArg(0))) | 
| Tyker | b0561b3 | 2019-11-17 11:41:55 +0100 | [diff] [blame] | 9034 | return Visit(ME->getSubExpr()); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9035 |  | 
| Richard Smith | b8348f5 | 2016-05-12 22:16:28 +0000 | [diff] [blame] | 9036 | if (ZeroInit && !ZeroInitialization(E, T)) | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9037 | return false; | 
|  | 9038 |  | 
| Craig Topper | 5fc8fc2 | 2014-08-27 06:28:36 +0000 | [diff] [blame] | 9039 | auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 9040 | return HandleConstructorCall(E, This, Args, | 
|  | 9041 | cast<CXXConstructorDecl>(Definition), Info, | 
|  | 9042 | Result); | 
|  | 9043 | } | 
|  | 9044 |  | 
|  | 9045 | bool RecordExprEvaluator::VisitCXXInheritedCtorInitExpr( | 
|  | 9046 | const CXXInheritedCtorInitExpr *E) { | 
|  | 9047 | if (!Info.CurrentCall) { | 
|  | 9048 | assert(Info.checkingPotentialConstantExpression()); | 
|  | 9049 | return false; | 
|  | 9050 | } | 
|  | 9051 |  | 
|  | 9052 | const CXXConstructorDecl *FD = E->getConstructor(); | 
|  | 9053 | if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) | 
|  | 9054 | return false; | 
|  | 9055 |  | 
|  | 9056 | const FunctionDecl *Definition = nullptr; | 
|  | 9057 | auto Body = FD->getBody(Definition); | 
|  | 9058 |  | 
|  | 9059 | if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) | 
|  | 9060 | return false; | 
|  | 9061 |  | 
|  | 9062 | return HandleConstructorCall(E, This, Info.CurrentCall->Arguments, | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 9063 | cast<CXXConstructorDecl>(Definition), Info, | 
|  | 9064 | Result); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9065 | } | 
|  | 9066 |  | 
| Richard Smith | cc1b96d | 2013-06-12 22:31:48 +0000 | [diff] [blame] | 9067 | bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( | 
|  | 9068 | const CXXStdInitializerListExpr *E) { | 
|  | 9069 | const ConstantArrayType *ArrayType = | 
|  | 9070 | Info.Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); | 
|  | 9071 |  | 
|  | 9072 | LValue Array; | 
|  | 9073 | if (!EvaluateLValue(E->getSubExpr(), Array, Info)) | 
|  | 9074 | return false; | 
|  | 9075 |  | 
|  | 9076 | // Get a pointer to the first element of the array. | 
|  | 9077 | Array.addArray(Info, E, ArrayType); | 
|  | 9078 |  | 
|  | 9079 | // FIXME: Perform the checks on the field types in SemaInit. | 
|  | 9080 | RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl(); | 
|  | 9081 | RecordDecl::field_iterator Field = Record->field_begin(); | 
|  | 9082 | if (Field == Record->field_end()) | 
|  | 9083 | return Error(E); | 
|  | 9084 |  | 
|  | 9085 | // Start pointer. | 
|  | 9086 | if (!Field->getType()->isPointerType() || | 
|  | 9087 | !Info.Ctx.hasSameType(Field->getType()->getPointeeType(), | 
|  | 9088 | ArrayType->getElementType())) | 
|  | 9089 | return Error(E); | 
|  | 9090 |  | 
|  | 9091 | // FIXME: What if the initializer_list type has base classes, etc? | 
|  | 9092 | Result = APValue(APValue::UninitStruct(), 0, 2); | 
|  | 9093 | Array.moveInto(Result.getStructField(0)); | 
|  | 9094 |  | 
|  | 9095 | if (++Field == Record->field_end()) | 
|  | 9096 | return Error(E); | 
|  | 9097 |  | 
|  | 9098 | if (Field->getType()->isPointerType() && | 
|  | 9099 | Info.Ctx.hasSameType(Field->getType()->getPointeeType(), | 
|  | 9100 | ArrayType->getElementType())) { | 
|  | 9101 | // End pointer. | 
|  | 9102 | if (!HandleLValueArrayAdjustment(Info, E, Array, | 
|  | 9103 | ArrayType->getElementType(), | 
|  | 9104 | ArrayType->getSize().getZExtValue())) | 
|  | 9105 | return false; | 
|  | 9106 | Array.moveInto(Result.getStructField(1)); | 
|  | 9107 | } else if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType())) | 
|  | 9108 | // Length. | 
|  | 9109 | Result.getStructField(1) = APValue(APSInt(ArrayType->getSize())); | 
|  | 9110 | else | 
|  | 9111 | return Error(E); | 
|  | 9112 |  | 
|  | 9113 | if (++Field != Record->field_end()) | 
|  | 9114 | return Error(E); | 
|  | 9115 |  | 
|  | 9116 | return true; | 
|  | 9117 | } | 
|  | 9118 |  | 
| Faisal Vali | c72a08c | 2017-01-09 03:02:53 +0000 | [diff] [blame] | 9119 | bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { | 
|  | 9120 | const CXXRecordDecl *ClosureClass = E->getLambdaClass(); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 9121 | if (ClosureClass->isInvalidDecl()) | 
|  | 9122 | return false; | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 9123 |  | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 9124 | const size_t NumFields = | 
|  | 9125 | std::distance(ClosureClass->field_begin(), ClosureClass->field_end()); | 
| Benjamin Kramer | aad1bdc | 2017-02-16 14:08:41 +0000 | [diff] [blame] | 9126 |  | 
|  | 9127 | assert(NumFields == (size_t)std::distance(E->capture_init_begin(), | 
|  | 9128 | E->capture_init_end()) && | 
|  | 9129 | "The number of lambda capture initializers should equal the number of " | 
|  | 9130 | "fields within the closure type"); | 
|  | 9131 |  | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 9132 | Result = APValue(APValue::UninitStruct(), /*NumBases*/0, NumFields); | 
|  | 9133 | // Iterate through all the lambda's closure object's fields and initialize | 
|  | 9134 | // them. | 
|  | 9135 | auto *CaptureInitIt = E->capture_init_begin(); | 
|  | 9136 | const LambdaCapture *CaptureIt = ClosureClass->captures_begin(); | 
|  | 9137 | bool Success = true; | 
|  | 9138 | for (const auto *Field : ClosureClass->fields()) { | 
|  | 9139 | assert(CaptureInitIt != E->capture_init_end()); | 
|  | 9140 | // Get the initializer for this field | 
|  | 9141 | Expr *const CurFieldInit = *CaptureInitIt++; | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 9142 |  | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 9143 | // If there is no initializer, either this is a VLA or an error has | 
|  | 9144 | // occurred. | 
|  | 9145 | if (!CurFieldInit) | 
|  | 9146 | return Error(E); | 
|  | 9147 |  | 
|  | 9148 | APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); | 
|  | 9149 | if (!EvaluateInPlace(FieldVal, Info, This, CurFieldInit)) { | 
|  | 9150 | if (!Info.keepEvaluatingAfterFailure()) | 
|  | 9151 | return false; | 
|  | 9152 | Success = false; | 
|  | 9153 | } | 
|  | 9154 | ++CaptureIt; | 
| Faisal Vali | c72a08c | 2017-01-09 03:02:53 +0000 | [diff] [blame] | 9155 | } | 
| Faisal Vali | 051e3a2 | 2017-02-16 04:12:21 +0000 | [diff] [blame] | 9156 | return Success; | 
| Faisal Vali | c72a08c | 2017-01-09 03:02:53 +0000 | [diff] [blame] | 9157 | } | 
|  | 9158 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9159 | static bool EvaluateRecord(const Expr *E, const LValue &This, | 
|  | 9160 | APValue &Result, EvalInfo &Info) { | 
|  | 9161 | assert(E->isRValue() && E->getType()->isRecordType() && | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9162 | "can't evaluate expression as a record rvalue"); | 
|  | 9163 | return RecordExprEvaluator(Info, This, Result).Visit(E); | 
|  | 9164 | } | 
|  | 9165 |  | 
|  | 9166 | //===----------------------------------------------------------------------===// | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9167 | // Temporary Evaluation | 
|  | 9168 | // | 
|  | 9169 | // Temporaries are represented in the AST as rvalues, but generally behave like | 
|  | 9170 | // lvalues. The full-object of which the temporary is a subobject is implicitly | 
|  | 9171 | // materialized so that a reference can bind to it. | 
|  | 9172 | //===----------------------------------------------------------------------===// | 
|  | 9173 | namespace { | 
|  | 9174 | class TemporaryExprEvaluator | 
|  | 9175 | : public LValueExprEvaluatorBase<TemporaryExprEvaluator> { | 
|  | 9176 | public: | 
|  | 9177 | TemporaryExprEvaluator(EvalInfo &Info, LValue &Result) : | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 9178 | LValueExprEvaluatorBaseTy(Info, Result, false) {} | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9179 |  | 
|  | 9180 | /// Visit an expression which constructs the value of this temporary. | 
|  | 9181 | bool VisitConstructExpr(const Expr *E) { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 9182 | APValue &Value = | 
|  | 9183 | Info.CurrentCall->createTemporary(E, E->getType(), false, Result); | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 9184 | return EvaluateInPlace(Value, Info, Result, E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9185 | } | 
|  | 9186 |  | 
|  | 9187 | bool VisitCastExpr(const CastExpr *E) { | 
|  | 9188 | switch (E->getCastKind()) { | 
|  | 9189 | default: | 
|  | 9190 | return LValueExprEvaluatorBaseTy::VisitCastExpr(E); | 
|  | 9191 |  | 
|  | 9192 | case CK_ConstructorConversion: | 
|  | 9193 | return VisitConstructExpr(E->getSubExpr()); | 
|  | 9194 | } | 
|  | 9195 | } | 
|  | 9196 | bool VisitInitListExpr(const InitListExpr *E) { | 
|  | 9197 | return VisitConstructExpr(E); | 
|  | 9198 | } | 
|  | 9199 | bool VisitCXXConstructExpr(const CXXConstructExpr *E) { | 
|  | 9200 | return VisitConstructExpr(E); | 
|  | 9201 | } | 
|  | 9202 | bool VisitCallExpr(const CallExpr *E) { | 
|  | 9203 | return VisitConstructExpr(E); | 
|  | 9204 | } | 
| Richard Smith | 513955c | 2014-12-17 19:24:30 +0000 | [diff] [blame] | 9205 | bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) { | 
|  | 9206 | return VisitConstructExpr(E); | 
|  | 9207 | } | 
| Faisal Vali | c72a08c | 2017-01-09 03:02:53 +0000 | [diff] [blame] | 9208 | bool VisitLambdaExpr(const LambdaExpr *E) { | 
|  | 9209 | return VisitConstructExpr(E); | 
|  | 9210 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9211 | }; | 
|  | 9212 | } // end anonymous namespace | 
|  | 9213 |  | 
|  | 9214 | /// Evaluate an expression of record type as a temporary. | 
|  | 9215 | static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) { | 
| Richard Smith | d0b111c | 2011-12-19 22:01:37 +0000 | [diff] [blame] | 9216 | assert(E->isRValue() && E->getType()->isRecordType()); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9217 | return TemporaryExprEvaluator(Info, Result).Visit(E); | 
|  | 9218 | } | 
|  | 9219 |  | 
|  | 9220 | //===----------------------------------------------------------------------===// | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9221 | // Vector Evaluation | 
|  | 9222 | //===----------------------------------------------------------------------===// | 
|  | 9223 |  | 
|  | 9224 | namespace { | 
| Benjamin Kramer | 26222b6 | 2009-11-28 19:03:38 +0000 | [diff] [blame] | 9225 | class VectorExprEvaluator | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 9226 | : public ExprEvaluatorBase<VectorExprEvaluator> { | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9227 | APValue &Result; | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9228 | public: | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 9229 |  | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9230 | VectorExprEvaluator(EvalInfo &info, APValue &Result) | 
|  | 9231 | : ExprEvaluatorBaseTy(info), Result(Result) {} | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 9232 |  | 
| Craig Topper | 9798b93 | 2015-09-29 04:30:05 +0000 | [diff] [blame] | 9233 | bool Success(ArrayRef<APValue> V, const Expr *E) { | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9234 | assert(V.size() == E->getType()->castAs<VectorType>()->getNumElements()); | 
|  | 9235 | // FIXME: remove this APValue copy. | 
|  | 9236 | Result = APValue(V.data(), V.size()); | 
|  | 9237 | return true; | 
|  | 9238 | } | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9239 | bool Success(const APValue &V, const Expr *E) { | 
| Richard Smith | ed5165f | 2011-11-04 05:33:44 +0000 | [diff] [blame] | 9240 | assert(V.isVector()); | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9241 | Result = V; | 
|  | 9242 | return true; | 
|  | 9243 | } | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9244 | bool ZeroInitialization(const Expr *E); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 9245 |  | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9246 | bool VisitUnaryReal(const UnaryOperator *E) | 
| Eli Friedman | 3ae5911 | 2009-02-23 04:23:56 +0000 | [diff] [blame] | 9247 | { return Visit(E->getSubExpr()); } | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9248 | bool VisitCastExpr(const CastExpr* E); | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9249 | bool VisitInitListExpr(const InitListExpr *E); | 
|  | 9250 | bool VisitUnaryImag(const UnaryOperator *E); | 
| Eli Friedman | 3ae5911 | 2009-02-23 04:23:56 +0000 | [diff] [blame] | 9251 | // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div, | 
| Eli Friedman | c2b5017 | 2009-02-22 11:46:18 +0000 | [diff] [blame] | 9252 | //                 binary comparisons, binary and/or/xor, | 
| Eli Friedman | 3ae5911 | 2009-02-23 04:23:56 +0000 | [diff] [blame] | 9253 | //                 shufflevector, ExtVectorElementExpr | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9254 | }; | 
|  | 9255 | } // end anonymous namespace | 
|  | 9256 |  | 
|  | 9257 | static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 9258 | assert(E->isRValue() && E->getType()->isVectorType() &&"not a vector rvalue"); | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9259 | return VectorExprEvaluator(Info, Result).Visit(E); | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9260 | } | 
|  | 9261 |  | 
| George Burgess IV | 533ff00 | 2015-12-11 00:23:35 +0000 | [diff] [blame] | 9262 | bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) { | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9263 | const VectorType *VTy = E->getType()->castAs<VectorType>(); | 
| Nate Begeman | ef1a7fa | 2009-07-01 07:50:47 +0000 | [diff] [blame] | 9264 | unsigned NElts = VTy->getNumElements(); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 9265 |  | 
| Richard Smith | 161f09a | 2011-12-06 22:44:34 +0000 | [diff] [blame] | 9266 | const Expr *SE = E->getSubExpr(); | 
| Nate Begeman | 2ffd384 | 2009-06-26 18:22:18 +0000 | [diff] [blame] | 9267 | QualType SETy = SE->getType(); | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9268 |  | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 9269 | switch (E->getCastKind()) { | 
|  | 9270 | case CK_VectorSplat: { | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9271 | APValue Val = APValue(); | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 9272 | if (SETy->isIntegerType()) { | 
|  | 9273 | APSInt IntResult; | 
|  | 9274 | if (!EvaluateInteger(SE, IntResult, Info)) | 
| George Burgess IV | 533ff00 | 2015-12-11 00:23:35 +0000 | [diff] [blame] | 9275 | return false; | 
|  | 9276 | Val = APValue(std::move(IntResult)); | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 9277 | } else if (SETy->isRealFloatingType()) { | 
| George Burgess IV | 533ff00 | 2015-12-11 00:23:35 +0000 | [diff] [blame] | 9278 | APFloat FloatResult(0.0); | 
|  | 9279 | if (!EvaluateFloat(SE, FloatResult, Info)) | 
|  | 9280 | return false; | 
|  | 9281 | Val = APValue(std::move(FloatResult)); | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 9282 | } else { | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9283 | return Error(E); | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 9284 | } | 
| Nate Begeman | ef1a7fa | 2009-07-01 07:50:47 +0000 | [diff] [blame] | 9285 |  | 
|  | 9286 | // Splat and create vector APValue. | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9287 | SmallVector<APValue, 4> Elts(NElts, Val); | 
|  | 9288 | return Success(Elts, E); | 
| Nate Begeman | 2ffd384 | 2009-06-26 18:22:18 +0000 | [diff] [blame] | 9289 | } | 
| Eli Friedman | 803acb3 | 2011-12-22 03:51:45 +0000 | [diff] [blame] | 9290 | case CK_BitCast: { | 
|  | 9291 | // Evaluate the operand into an APInt we can extract from. | 
|  | 9292 | llvm::APInt SValInt; | 
|  | 9293 | if (!EvalAndBitcastToAPInt(Info, SE, SValInt)) | 
|  | 9294 | return false; | 
|  | 9295 | // Extract the elements | 
|  | 9296 | QualType EltTy = VTy->getElementType(); | 
|  | 9297 | unsigned EltSize = Info.Ctx.getTypeSize(EltTy); | 
|  | 9298 | bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); | 
|  | 9299 | SmallVector<APValue, 4> Elts; | 
|  | 9300 | if (EltTy->isRealFloatingType()) { | 
|  | 9301 | const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); | 
| Eli Friedman | 803acb3 | 2011-12-22 03:51:45 +0000 | [diff] [blame] | 9302 | unsigned FloatEltSize = EltSize; | 
| Stephan Bergmann | 17c7f70 | 2016-12-14 11:57:17 +0000 | [diff] [blame] | 9303 | if (&Sem == &APFloat::x87DoubleExtended()) | 
| Eli Friedman | 803acb3 | 2011-12-22 03:51:45 +0000 | [diff] [blame] | 9304 | FloatEltSize = 80; | 
|  | 9305 | for (unsigned i = 0; i < NElts; i++) { | 
|  | 9306 | llvm::APInt Elt; | 
|  | 9307 | if (BigEndian) | 
|  | 9308 | Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize); | 
|  | 9309 | else | 
|  | 9310 | Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize); | 
| Tim Northover | 178723a | 2013-01-22 09:46:51 +0000 | [diff] [blame] | 9311 | Elts.push_back(APValue(APFloat(Sem, Elt))); | 
| Eli Friedman | 803acb3 | 2011-12-22 03:51:45 +0000 | [diff] [blame] | 9312 | } | 
|  | 9313 | } else if (EltTy->isIntegerType()) { | 
|  | 9314 | for (unsigned i = 0; i < NElts; i++) { | 
|  | 9315 | llvm::APInt Elt; | 
|  | 9316 | if (BigEndian) | 
|  | 9317 | Elt = SValInt.rotl(i*EltSize+EltSize).zextOrTrunc(EltSize); | 
|  | 9318 | else | 
|  | 9319 | Elt = SValInt.rotr(i*EltSize).zextOrTrunc(EltSize); | 
|  | 9320 | Elts.push_back(APValue(APSInt(Elt, EltTy->isSignedIntegerType()))); | 
|  | 9321 | } | 
|  | 9322 | } else { | 
|  | 9323 | return Error(E); | 
|  | 9324 | } | 
|  | 9325 | return Success(Elts, E); | 
|  | 9326 | } | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 9327 | default: | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 9328 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 9329 | } | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9330 | } | 
|  | 9331 |  | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9332 | bool | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9333 | VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9334 | const VectorType *VT = E->getType()->castAs<VectorType>(); | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9335 | unsigned NumInits = E->getNumInits(); | 
| Eli Friedman | 3ae5911 | 2009-02-23 04:23:56 +0000 | [diff] [blame] | 9336 | unsigned NumElements = VT->getNumElements(); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 9337 |  | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9338 | QualType EltTy = VT->getElementType(); | 
| Chris Lattner | 0e62c1c | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 9339 | SmallVector<APValue, 4> Elements; | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9340 |  | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9341 | // The number of initializers can be less than the number of | 
|  | 9342 | // vector elements. For OpenCL, this can be due to nested vector | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 9343 | // initialization. For GCC compatibility, missing trailing elements | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9344 | // should be initialized with zeroes. | 
|  | 9345 | unsigned CountInits = 0, CountElts = 0; | 
|  | 9346 | while (CountElts < NumElements) { | 
|  | 9347 | // Handle nested vector initialization. | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 9348 | if (CountInits < NumInits | 
| Eli Friedman | 1409e6e | 2013-09-17 04:07:02 +0000 | [diff] [blame] | 9349 | && E->getInit(CountInits)->getType()->isVectorType()) { | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9350 | APValue v; | 
|  | 9351 | if (!EvaluateVector(E->getInit(CountInits), v, Info)) | 
|  | 9352 | return Error(E); | 
|  | 9353 | unsigned vlen = v.getVectorLength(); | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 9354 | for (unsigned j = 0; j < vlen; j++) | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9355 | Elements.push_back(v.getVectorElt(j)); | 
|  | 9356 | CountElts += vlen; | 
|  | 9357 | } else if (EltTy->isIntegerType()) { | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9358 | llvm::APSInt sInt(32); | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9359 | if (CountInits < NumInits) { | 
|  | 9360 | if (!EvaluateInteger(E->getInit(CountInits), sInt, Info)) | 
| Richard Smith | ac2f0b1 | 2012-03-13 20:58:32 +0000 | [diff] [blame] | 9361 | return false; | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9362 | } else // trailing integer zero. | 
|  | 9363 | sInt = Info.Ctx.MakeIntValue(0, EltTy); | 
|  | 9364 | Elements.push_back(APValue(sInt)); | 
|  | 9365 | CountElts++; | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9366 | } else { | 
|  | 9367 | llvm::APFloat f(0.0); | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9368 | if (CountInits < NumInits) { | 
|  | 9369 | if (!EvaluateFloat(E->getInit(CountInits), f, Info)) | 
| Richard Smith | ac2f0b1 | 2012-03-13 20:58:32 +0000 | [diff] [blame] | 9370 | return false; | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9371 | } else // trailing float zero. | 
|  | 9372 | f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); | 
|  | 9373 | Elements.push_back(APValue(f)); | 
|  | 9374 | CountElts++; | 
| John McCall | 875679e | 2010-06-11 17:54:15 +0000 | [diff] [blame] | 9375 | } | 
| Eli Friedman | b9c7129 | 2012-01-03 23:24:20 +0000 | [diff] [blame] | 9376 | CountInits++; | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9377 | } | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9378 | return Success(Elements, E); | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9379 | } | 
|  | 9380 |  | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9381 | bool | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9382 | VectorExprEvaluator::ZeroInitialization(const Expr *E) { | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 9383 | const auto *VT = E->getType()->castAs<VectorType>(); | 
| Eli Friedman | 3ae5911 | 2009-02-23 04:23:56 +0000 | [diff] [blame] | 9384 | QualType EltTy = VT->getElementType(); | 
|  | 9385 | APValue ZeroElement; | 
|  | 9386 | if (EltTy->isIntegerType()) | 
|  | 9387 | ZeroElement = APValue(Info.Ctx.MakeIntValue(0, EltTy)); | 
|  | 9388 | else | 
|  | 9389 | ZeroElement = | 
|  | 9390 | APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy))); | 
|  | 9391 |  | 
| Chris Lattner | 0e62c1c | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 9392 | SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement); | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9393 | return Success(Elements, E); | 
| Eli Friedman | 3ae5911 | 2009-02-23 04:23:56 +0000 | [diff] [blame] | 9394 | } | 
|  | 9395 |  | 
| Richard Smith | 2d40634 | 2011-10-22 21:10:00 +0000 | [diff] [blame] | 9396 | bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { | 
| Richard Smith | 4a67812 | 2011-10-24 18:44:57 +0000 | [diff] [blame] | 9397 | VisitIgnoredValue(E->getSubExpr()); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9398 | return ZeroInitialization(E); | 
| Eli Friedman | 3ae5911 | 2009-02-23 04:23:56 +0000 | [diff] [blame] | 9399 | } | 
|  | 9400 |  | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 9401 | //===----------------------------------------------------------------------===// | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9402 | // Array Evaluation | 
|  | 9403 | //===----------------------------------------------------------------------===// | 
|  | 9404 |  | 
|  | 9405 | namespace { | 
|  | 9406 | class ArrayExprEvaluator | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 9407 | : public ExprEvaluatorBase<ArrayExprEvaluator> { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9408 | const LValue &This; | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9409 | APValue &Result; | 
|  | 9410 | public: | 
|  | 9411 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9412 | ArrayExprEvaluator(EvalInfo &Info, const LValue &This, APValue &Result) | 
|  | 9413 | : ExprEvaluatorBaseTy(Info), This(This), Result(Result) {} | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9414 |  | 
|  | 9415 | bool Success(const APValue &V, const Expr *E) { | 
| Eli Friedman | 3bf72d7 | 2019-02-08 21:18:46 +0000 | [diff] [blame] | 9416 | assert(V.isArray() && "expected array"); | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9417 | Result = V; | 
|  | 9418 | return true; | 
|  | 9419 | } | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9420 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9421 | bool ZeroInitialization(const Expr *E) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9422 | const ConstantArrayType *CAT = | 
|  | 9423 | Info.Ctx.getAsConstantArrayType(E->getType()); | 
|  | 9424 | if (!CAT) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 9425 | return Error(E); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9426 |  | 
|  | 9427 | Result = APValue(APValue::UninitArray(), 0, | 
|  | 9428 | CAT->getSize().getZExtValue()); | 
|  | 9429 | if (!Result.hasArrayFiller()) return true; | 
|  | 9430 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9431 | // Zero-initialize all elements. | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9432 | LValue Subobject = This; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 9433 | Subobject.addArray(Info, E, CAT); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9434 | ImplicitValueInitExpr VIE(CAT->getElementType()); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 9435 | return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, &VIE); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9436 | } | 
|  | 9437 |  | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 9438 | bool VisitCallExpr(const CallExpr *E) { | 
|  | 9439 | return handleCallExpr(E, Result, &This); | 
|  | 9440 | } | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 9441 | bool VisitInitListExpr(const InitListExpr *E, | 
|  | 9442 | QualType AllocType = QualType()); | 
| Richard Smith | 410306b | 2016-12-12 02:53:20 +0000 | [diff] [blame] | 9443 | bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9444 | bool VisitCXXConstructExpr(const CXXConstructExpr *E); | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9445 | bool VisitCXXConstructExpr(const CXXConstructExpr *E, | 
|  | 9446 | const LValue &Subobject, | 
|  | 9447 | APValue *Value, QualType Type); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 9448 | bool VisitStringLiteral(const StringLiteral *E, | 
|  | 9449 | QualType AllocType = QualType()) { | 
|  | 9450 | expandStringLiteral(Info, E, Result, AllocType); | 
| Eli Friedman | 3bf72d7 | 2019-02-08 21:18:46 +0000 | [diff] [blame] | 9451 | return true; | 
|  | 9452 | } | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9453 | }; | 
|  | 9454 | } // end anonymous namespace | 
|  | 9455 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9456 | static bool EvaluateArray(const Expr *E, const LValue &This, | 
|  | 9457 | APValue &Result, EvalInfo &Info) { | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9458 | assert(E->isRValue() && E->getType()->isArrayType() && "not an array rvalue"); | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9459 | return ArrayExprEvaluator(Info, This, Result).Visit(E); | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9460 | } | 
|  | 9461 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 9462 | static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This, | 
|  | 9463 | APValue &Result, const InitListExpr *ILE, | 
|  | 9464 | QualType AllocType) { | 
|  | 9465 | assert(ILE->isRValue() && ILE->getType()->isArrayType() && | 
|  | 9466 | "not an array rvalue"); | 
|  | 9467 | return ArrayExprEvaluator(Info, This, Result) | 
|  | 9468 | .VisitInitListExpr(ILE, AllocType); | 
|  | 9469 | } | 
|  | 9470 |  | 
| Ivan A. Kosarev | 01df519 | 2018-02-14 13:10:35 +0000 | [diff] [blame] | 9471 | // Return true iff the given array filler may depend on the element index. | 
|  | 9472 | static bool MaybeElementDependentArrayFiller(const Expr *FillerExpr) { | 
|  | 9473 | // For now, just whitelist non-class value-initialization and initialization | 
|  | 9474 | // lists comprised of them. | 
|  | 9475 | if (isa<ImplicitValueInitExpr>(FillerExpr)) | 
|  | 9476 | return false; | 
|  | 9477 | if (const InitListExpr *ILE = dyn_cast<InitListExpr>(FillerExpr)) { | 
|  | 9478 | for (unsigned I = 0, E = ILE->getNumInits(); I != E; ++I) { | 
|  | 9479 | if (MaybeElementDependentArrayFiller(ILE->getInit(I))) | 
|  | 9480 | return true; | 
|  | 9481 | } | 
|  | 9482 | return false; | 
|  | 9483 | } | 
|  | 9484 | return true; | 
|  | 9485 | } | 
|  | 9486 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 9487 | bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E, | 
|  | 9488 | QualType AllocType) { | 
|  | 9489 | const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType( | 
|  | 9490 | AllocType.isNull() ? E->getType() : AllocType); | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9491 | if (!CAT) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 9492 | return Error(E); | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9493 |  | 
| Richard Smith | ca2cfbf | 2011-12-22 01:07:19 +0000 | [diff] [blame] | 9494 | // C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...] | 
|  | 9495 | // an appropriately-typed string literal enclosed in braces. | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 9496 | if (E->isStringLiteralInit()) { | 
|  | 9497 | auto *SL = dyn_cast<StringLiteral>(E->getInit(0)->IgnoreParens()); | 
|  | 9498 | // FIXME: Support ObjCEncodeExpr here once we support it in | 
|  | 9499 | // ArrayExprEvaluator generally. | 
|  | 9500 | if (!SL) | 
|  | 9501 | return Error(E); | 
|  | 9502 | return VisitStringLiteral(SL, AllocType); | 
|  | 9503 | } | 
| Richard Smith | ca2cfbf | 2011-12-22 01:07:19 +0000 | [diff] [blame] | 9504 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 9505 | bool Success = true; | 
|  | 9506 |  | 
| Richard Smith | 1b9f2eb | 2012-07-07 22:48:24 +0000 | [diff] [blame] | 9507 | assert((!Result.isArray() || Result.getArrayInitializedElts() == 0) && | 
|  | 9508 | "zero-initialized array shouldn't have any initialized elts"); | 
|  | 9509 | APValue Filler; | 
|  | 9510 | if (Result.isArray() && Result.hasArrayFiller()) | 
|  | 9511 | Filler = Result.getArrayFiller(); | 
|  | 9512 |  | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9513 | unsigned NumEltsToInit = E->getNumInits(); | 
|  | 9514 | unsigned NumElts = CAT->getSize().getZExtValue(); | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 9515 | const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr; | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9516 |  | 
|  | 9517 | // If the initializer might depend on the array index, run it for each | 
| Ivan A. Kosarev | 01df519 | 2018-02-14 13:10:35 +0000 | [diff] [blame] | 9518 | // array element. | 
|  | 9519 | if (NumEltsToInit != NumElts && MaybeElementDependentArrayFiller(FillerExpr)) | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9520 | NumEltsToInit = NumElts; | 
|  | 9521 |  | 
| Nicola Zaghen | 3538b39 | 2018-05-15 13:30:56 +0000 | [diff] [blame] | 9522 | LLVM_DEBUG(llvm::dbgs() << "The number of elements to initialize: " | 
|  | 9523 | << NumEltsToInit << ".\n"); | 
| Ivan A. Kosarev | 01df519 | 2018-02-14 13:10:35 +0000 | [diff] [blame] | 9524 |  | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9525 | Result = APValue(APValue::UninitArray(), NumEltsToInit, NumElts); | 
| Richard Smith | 1b9f2eb | 2012-07-07 22:48:24 +0000 | [diff] [blame] | 9526 |  | 
|  | 9527 | // If the array was previously zero-initialized, preserve the | 
|  | 9528 | // zero-initialized values. | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 9529 | if (Filler.hasValue()) { | 
| Richard Smith | 1b9f2eb | 2012-07-07 22:48:24 +0000 | [diff] [blame] | 9530 | for (unsigned I = 0, E = Result.getArrayInitializedElts(); I != E; ++I) | 
|  | 9531 | Result.getArrayInitializedElt(I) = Filler; | 
|  | 9532 | if (Result.hasArrayFiller()) | 
|  | 9533 | Result.getArrayFiller() = Filler; | 
|  | 9534 | } | 
|  | 9535 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9536 | LValue Subobject = This; | 
| Richard Smith | a8105bc | 2012-01-06 16:39:00 +0000 | [diff] [blame] | 9537 | Subobject.addArray(Info, E, CAT); | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9538 | for (unsigned Index = 0; Index != NumEltsToInit; ++Index) { | 
|  | 9539 | const Expr *Init = | 
|  | 9540 | Index < E->getNumInits() ? E->getInit(Index) : FillerExpr; | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 9541 | if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9542 | Info, Subobject, Init) || | 
|  | 9543 | !HandleLValueArrayAdjustment(Info, Init, Subobject, | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 9544 | CAT->getElementType(), 1)) { | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 9545 | if (!Info.noteFailure()) | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 9546 | return false; | 
|  | 9547 | Success = false; | 
|  | 9548 | } | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 9549 | } | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9550 |  | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9551 | if (!Result.hasArrayFiller()) | 
|  | 9552 | return Success; | 
|  | 9553 |  | 
|  | 9554 | // If we get here, we have a trivial filler, which we can just evaluate | 
|  | 9555 | // once and splat over the rest of the array elements. | 
|  | 9556 | assert(FillerExpr && "no array filler for incomplete init list"); | 
|  | 9557 | return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, | 
|  | 9558 | FillerExpr) && Success; | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9559 | } | 
|  | 9560 |  | 
| Richard Smith | 410306b | 2016-12-12 02:53:20 +0000 | [diff] [blame] | 9561 | bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 9562 | LValue CommonLV; | 
| Richard Smith | 410306b | 2016-12-12 02:53:20 +0000 | [diff] [blame] | 9563 | if (E->getCommonExpr() && | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 9564 | !Evaluate(Info.CurrentCall->createTemporary( | 
|  | 9565 | E->getCommonExpr(), | 
|  | 9566 | getStorageType(Info.Ctx, E->getCommonExpr()), false, | 
|  | 9567 | CommonLV), | 
| Richard Smith | 410306b | 2016-12-12 02:53:20 +0000 | [diff] [blame] | 9568 | Info, E->getCommonExpr()->getSourceExpr())) | 
|  | 9569 | return false; | 
|  | 9570 |  | 
|  | 9571 | auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe()); | 
|  | 9572 |  | 
|  | 9573 | uint64_t Elements = CAT->getSize().getZExtValue(); | 
|  | 9574 | Result = APValue(APValue::UninitArray(), Elements, Elements); | 
|  | 9575 |  | 
|  | 9576 | LValue Subobject = This; | 
|  | 9577 | Subobject.addArray(Info, E, CAT); | 
|  | 9578 |  | 
|  | 9579 | bool Success = true; | 
|  | 9580 | for (EvalInfo::ArrayInitLoopIndex Index(Info); Index != Elements; ++Index) { | 
|  | 9581 | if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), | 
|  | 9582 | Info, Subobject, E->getSubExpr()) || | 
|  | 9583 | !HandleLValueArrayAdjustment(Info, E, Subobject, | 
|  | 9584 | CAT->getElementType(), 1)) { | 
|  | 9585 | if (!Info.noteFailure()) | 
|  | 9586 | return false; | 
|  | 9587 | Success = false; | 
|  | 9588 | } | 
|  | 9589 | } | 
|  | 9590 |  | 
|  | 9591 | return Success; | 
|  | 9592 | } | 
|  | 9593 |  | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9594 | bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9595 | return VisitCXXConstructExpr(E, This, &Result, E->getType()); | 
|  | 9596 | } | 
| Richard Smith | 1b9f2eb | 2012-07-07 22:48:24 +0000 | [diff] [blame] | 9597 |  | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9598 | bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, | 
|  | 9599 | const LValue &Subobject, | 
|  | 9600 | APValue *Value, | 
|  | 9601 | QualType Type) { | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 9602 | bool HadZeroInit = Value->hasValue(); | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9603 |  | 
|  | 9604 | if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) { | 
|  | 9605 | unsigned N = CAT->getSize().getZExtValue(); | 
|  | 9606 |  | 
|  | 9607 | // Preserve the array filler if we had prior zero-initialization. | 
|  | 9608 | APValue Filler = | 
|  | 9609 | HadZeroInit && Value->hasArrayFiller() ? Value->getArrayFiller() | 
|  | 9610 | : APValue(); | 
|  | 9611 |  | 
|  | 9612 | *Value = APValue(APValue::UninitArray(), N, N); | 
|  | 9613 |  | 
|  | 9614 | if (HadZeroInit) | 
|  | 9615 | for (unsigned I = 0; I != N; ++I) | 
|  | 9616 | Value->getArrayInitializedElt(I) = Filler; | 
|  | 9617 |  | 
|  | 9618 | // Initialize the elements. | 
|  | 9619 | LValue ArrayElt = Subobject; | 
|  | 9620 | ArrayElt.addArray(Info, E, CAT); | 
|  | 9621 | for (unsigned I = 0; I != N; ++I) | 
|  | 9622 | if (!VisitCXXConstructExpr(E, ArrayElt, &Value->getArrayInitializedElt(I), | 
|  | 9623 | CAT->getElementType()) || | 
|  | 9624 | !HandleLValueArrayAdjustment(Info, E, ArrayElt, | 
|  | 9625 | CAT->getElementType(), 1)) | 
|  | 9626 | return false; | 
|  | 9627 |  | 
|  | 9628 | return true; | 
| Richard Smith | 1b9f2eb | 2012-07-07 22:48:24 +0000 | [diff] [blame] | 9629 | } | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9630 |  | 
| Richard Smith | 9543c5e | 2013-04-22 14:44:29 +0000 | [diff] [blame] | 9631 | if (!Type->isRecordType()) | 
| Richard Smith | 9fce7bc | 2012-07-10 22:12:55 +0000 | [diff] [blame] | 9632 | return Error(E); | 
|  | 9633 |  | 
| Richard Smith | b8348f5 | 2016-05-12 22:16:28 +0000 | [diff] [blame] | 9634 | return RecordExprEvaluator(Info, Subobject, *Value) | 
|  | 9635 | .VisitCXXConstructExpr(E, Type); | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 9636 | } | 
|  | 9637 |  | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 9638 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 9639 | // Integer Evaluation | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 9640 | // | 
|  | 9641 | // As a GNU extension, we support casting pointers to sufficiently-wide integer | 
|  | 9642 | // types and back in constant folding. Integer values are thus represented | 
|  | 9643 | // either as an integer-valued APValue, or as an lvalue-valued APValue. | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 9644 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 9645 |  | 
|  | 9646 | namespace { | 
| Benjamin Kramer | 26222b6 | 2009-11-28 19:03:38 +0000 | [diff] [blame] | 9647 | class IntExprEvaluator | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 9648 | : public ExprEvaluatorBase<IntExprEvaluator> { | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9649 | APValue &Result; | 
| Anders Carlsson | 0a1707c | 2008-07-08 05:13:58 +0000 | [diff] [blame] | 9650 | public: | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9651 | IntExprEvaluator(EvalInfo &info, APValue &result) | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 9652 | : ExprEvaluatorBaseTy(info), Result(result) {} | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 9653 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 9654 | bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) { | 
| Abramo Bagnara | 9ae292d | 2011-07-02 13:13:53 +0000 | [diff] [blame] | 9655 | assert(E->getType()->isIntegralOrEnumerationType() && | 
| Douglas Gregor | b90df60 | 2010-06-16 00:17:44 +0000 | [diff] [blame] | 9656 | "Invalid evaluation result."); | 
| Abramo Bagnara | 9ae292d | 2011-07-02 13:13:53 +0000 | [diff] [blame] | 9657 | assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() && | 
| Daniel Dunbar | e3c92bc | 2009-02-19 18:37:50 +0000 | [diff] [blame] | 9658 | "Invalid evaluation result."); | 
| Abramo Bagnara | 9ae292d | 2011-07-02 13:13:53 +0000 | [diff] [blame] | 9659 | assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && | 
| Daniel Dunbar | e3c92bc | 2009-02-19 18:37:50 +0000 | [diff] [blame] | 9660 | "Invalid evaluation result."); | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9661 | Result = APValue(SI); | 
| Daniel Dunbar | e3c92bc | 2009-02-19 18:37:50 +0000 | [diff] [blame] | 9662 | return true; | 
|  | 9663 | } | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 9664 | bool Success(const llvm::APSInt &SI, const Expr *E) { | 
|  | 9665 | return Success(SI, E, Result); | 
|  | 9666 | } | 
| Daniel Dunbar | e3c92bc | 2009-02-19 18:37:50 +0000 | [diff] [blame] | 9667 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 9668 | bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) { | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 9669 | assert(E->getType()->isIntegralOrEnumerationType() && | 
| Douglas Gregor | b90df60 | 2010-06-16 00:17:44 +0000 | [diff] [blame] | 9670 | "Invalid evaluation result."); | 
| Daniel Dunbar | ca097ad | 2009-02-19 20:17:33 +0000 | [diff] [blame] | 9671 | assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && | 
| Daniel Dunbar | e3c92bc | 2009-02-19 18:37:50 +0000 | [diff] [blame] | 9672 | "Invalid evaluation result."); | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9673 | Result = APValue(APSInt(I)); | 
| Douglas Gregor | 6ab2fa8 | 2011-05-20 16:38:50 +0000 | [diff] [blame] | 9674 | Result.getInt().setIsUnsigned( | 
|  | 9675 | E->getType()->isUnsignedIntegerOrEnumerationType()); | 
| Daniel Dunbar | 8aafc89 | 2009-02-19 09:06:44 +0000 | [diff] [blame] | 9676 | return true; | 
|  | 9677 | } | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 9678 | bool Success(const llvm::APInt &I, const Expr *E) { | 
|  | 9679 | return Success(I, E, Result); | 
|  | 9680 | } | 
| Daniel Dunbar | 8aafc89 | 2009-02-19 09:06:44 +0000 | [diff] [blame] | 9681 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 9682 | bool Success(uint64_t Value, const Expr *E, APValue &Result) { | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 9683 | assert(E->getType()->isIntegralOrEnumerationType() && | 
| Douglas Gregor | b90df60 | 2010-06-16 00:17:44 +0000 | [diff] [blame] | 9684 | "Invalid evaluation result."); | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9685 | Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType())); | 
| Daniel Dunbar | 8aafc89 | 2009-02-19 09:06:44 +0000 | [diff] [blame] | 9686 | return true; | 
|  | 9687 | } | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 9688 | bool Success(uint64_t Value, const Expr *E) { | 
|  | 9689 | return Success(Value, E, Result); | 
|  | 9690 | } | 
| Daniel Dunbar | 8aafc89 | 2009-02-19 09:06:44 +0000 | [diff] [blame] | 9691 |  | 
| Ken Dyck | dbc0191 | 2011-03-11 02:13:43 +0000 | [diff] [blame] | 9692 | bool Success(CharUnits Size, const Expr *E) { | 
|  | 9693 | return Success(Size.getQuantity(), E); | 
|  | 9694 | } | 
|  | 9695 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9696 | bool Success(const APValue &V, const Expr *E) { | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 9697 | if (V.isLValue() || V.isAddrLabelDiff() || V.isIndeterminate()) { | 
| Richard Smith | 9c8d1c5 | 2011-10-29 22:55:55 +0000 | [diff] [blame] | 9698 | Result = V; | 
|  | 9699 | return true; | 
|  | 9700 | } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 9701 | return Success(V.getInt(), E); | 
| Chris Lattner | fac05ae | 2008-11-12 07:43:42 +0000 | [diff] [blame] | 9702 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 9703 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9704 | bool ZeroInitialization(const Expr *E) { return Success(0, E); } | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 9705 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 9706 | //===--------------------------------------------------------------------===// | 
|  | 9707 | //                            Visitor Methods | 
|  | 9708 | //===--------------------------------------------------------------------===// | 
| Anders Carlsson | 0a1707c | 2008-07-08 05:13:58 +0000 | [diff] [blame] | 9709 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 9710 | bool VisitConstantExpr(const ConstantExpr *E); | 
|  | 9711 |  | 
| Chris Lattner | 7174bf3 | 2008-07-12 00:38:25 +0000 | [diff] [blame] | 9712 | bool VisitIntegerLiteral(const IntegerLiteral *E) { | 
| Daniel Dunbar | 8aafc89 | 2009-02-19 09:06:44 +0000 | [diff] [blame] | 9713 | return Success(E->getValue(), E); | 
| Chris Lattner | 7174bf3 | 2008-07-12 00:38:25 +0000 | [diff] [blame] | 9714 | } | 
|  | 9715 | bool VisitCharacterLiteral(const CharacterLiteral *E) { | 
| Daniel Dunbar | 8aafc89 | 2009-02-19 09:06:44 +0000 | [diff] [blame] | 9716 | return Success(E->getValue(), E); | 
| Chris Lattner | 7174bf3 | 2008-07-12 00:38:25 +0000 | [diff] [blame] | 9717 | } | 
| Eli Friedman | fb8a93f | 2009-11-24 05:28:59 +0000 | [diff] [blame] | 9718 |  | 
|  | 9719 | bool CheckReferencedDecl(const Expr *E, const Decl *D); | 
|  | 9720 | bool VisitDeclRefExpr(const DeclRefExpr *E) { | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 9721 | if (CheckReferencedDecl(E, E->getDecl())) | 
|  | 9722 | return true; | 
|  | 9723 |  | 
|  | 9724 | return ExprEvaluatorBaseTy::VisitDeclRefExpr(E); | 
| Eli Friedman | fb8a93f | 2009-11-24 05:28:59 +0000 | [diff] [blame] | 9725 | } | 
|  | 9726 | bool VisitMemberExpr(const MemberExpr *E) { | 
|  | 9727 | if (CheckReferencedDecl(E, E->getMemberDecl())) { | 
| David Majnemer | e9807b2 | 2016-02-26 04:23:19 +0000 | [diff] [blame] | 9728 | VisitIgnoredBaseExpression(E->getBase()); | 
| Eli Friedman | fb8a93f | 2009-11-24 05:28:59 +0000 | [diff] [blame] | 9729 | return true; | 
|  | 9730 | } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 9731 |  | 
|  | 9732 | return ExprEvaluatorBaseTy::VisitMemberExpr(E); | 
| Eli Friedman | fb8a93f | 2009-11-24 05:28:59 +0000 | [diff] [blame] | 9733 | } | 
|  | 9734 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 9735 | bool VisitCallExpr(const CallExpr *E); | 
| Richard Smith | 6328cbd | 2016-11-16 00:57:23 +0000 | [diff] [blame] | 9736 | bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); | 
| Chris Lattner | e13042c | 2008-07-11 19:10:17 +0000 | [diff] [blame] | 9737 | bool VisitBinaryOperator(const BinaryOperator *E); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 9738 | bool VisitOffsetOfExpr(const OffsetOfExpr *E); | 
| Chris Lattner | e13042c | 2008-07-11 19:10:17 +0000 | [diff] [blame] | 9739 | bool VisitUnaryOperator(const UnaryOperator *E); | 
| Anders Carlsson | 374b93d | 2008-07-08 05:49:43 +0000 | [diff] [blame] | 9740 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 9741 | bool VisitCastExpr(const CastExpr* E); | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 9742 | bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); | 
| Sebastian Redl | 6f28289 | 2008-11-11 17:56:53 +0000 | [diff] [blame] | 9743 |  | 
| Anders Carlsson | 9f9e424 | 2008-11-16 19:01:22 +0000 | [diff] [blame] | 9744 | bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { | 
| Daniel Dunbar | 8aafc89 | 2009-02-19 09:06:44 +0000 | [diff] [blame] | 9745 | return Success(E->getValue(), E); | 
| Anders Carlsson | 9f9e424 | 2008-11-16 19:01:22 +0000 | [diff] [blame] | 9746 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 9747 |  | 
| Ted Kremenek | e65b086 | 2012-03-06 20:05:56 +0000 | [diff] [blame] | 9748 | bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) { | 
|  | 9749 | return Success(E->getValue(), E); | 
|  | 9750 | } | 
| Richard Smith | 410306b | 2016-12-12 02:53:20 +0000 | [diff] [blame] | 9751 |  | 
|  | 9752 | bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) { | 
|  | 9753 | if (Info.ArrayInitIndex == uint64_t(-1)) { | 
|  | 9754 | // We were asked to evaluate this subexpression independent of the | 
|  | 9755 | // enclosing ArrayInitLoopExpr. We can't do that. | 
|  | 9756 | Info.FFDiag(E); | 
|  | 9757 | return false; | 
|  | 9758 | } | 
|  | 9759 | return Success(Info.ArrayInitIndex, E); | 
|  | 9760 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 9761 |  | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 9762 | // Note, GNU defines __null as an integer, not a pointer. | 
| Anders Carlsson | 39def3a | 2008-12-21 22:39:40 +0000 | [diff] [blame] | 9763 | bool VisitGNUNullExpr(const GNUNullExpr *E) { | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 9764 | return ZeroInitialization(E); | 
| Eli Friedman | 4e7a241 | 2009-02-27 04:45:43 +0000 | [diff] [blame] | 9765 | } | 
|  | 9766 |  | 
| Douglas Gregor | 29c42f2 | 2012-02-24 07:38:34 +0000 | [diff] [blame] | 9767 | bool VisitTypeTraitExpr(const TypeTraitExpr *E) { | 
|  | 9768 | return Success(E->getValue(), E); | 
|  | 9769 | } | 
|  | 9770 |  | 
| John Wiegley | 6242b6a | 2011-04-28 00:16:57 +0000 | [diff] [blame] | 9771 | bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { | 
|  | 9772 | return Success(E->getValue(), E); | 
|  | 9773 | } | 
|  | 9774 |  | 
| John Wiegley | f9f6584 | 2011-04-25 06:54:41 +0000 | [diff] [blame] | 9775 | bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { | 
|  | 9776 | return Success(E->getValue(), E); | 
|  | 9777 | } | 
|  | 9778 |  | 
| Eli Friedman | a1c7b6c | 2009-02-28 03:59:05 +0000 | [diff] [blame] | 9779 | bool VisitUnaryReal(const UnaryOperator *E); | 
| Eli Friedman | 4e7a241 | 2009-02-27 04:45:43 +0000 | [diff] [blame] | 9780 | bool VisitUnaryImag(const UnaryOperator *E); | 
|  | 9781 |  | 
| Sebastian Redl | 5f0180d | 2010-09-10 20:55:47 +0000 | [diff] [blame] | 9782 | bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); | 
| Douglas Gregor | 820ba7b | 2011-01-04 17:33:58 +0000 | [diff] [blame] | 9783 | bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 9784 | bool VisitSourceLocExpr(const SourceLocExpr *E); | 
| Saar Raz | 5d98ba6 | 2019-10-15 15:24:26 +0000 | [diff] [blame] | 9785 | bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E); | 
| Eli Friedman | 4e7a241 | 2009-02-27 04:45:43 +0000 | [diff] [blame] | 9786 | // FIXME: Missing: array subscript of vector, member of vector | 
| Anders Carlsson | 9c18165 | 2008-07-08 14:35:21 +0000 | [diff] [blame] | 9787 | }; | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9788 |  | 
|  | 9789 | class FixedPointExprEvaluator | 
|  | 9790 | : public ExprEvaluatorBase<FixedPointExprEvaluator> { | 
|  | 9791 | APValue &Result; | 
|  | 9792 |  | 
|  | 9793 | public: | 
|  | 9794 | FixedPointExprEvaluator(EvalInfo &info, APValue &result) | 
|  | 9795 | : ExprEvaluatorBaseTy(info), Result(result) {} | 
|  | 9796 |  | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9797 | bool Success(const llvm::APInt &I, const Expr *E) { | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 9798 | return Success( | 
|  | 9799 | APFixedPoint(I, Info.Ctx.getFixedPointSemantics(E->getType())), E); | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9800 | } | 
|  | 9801 |  | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9802 | bool Success(uint64_t Value, const Expr *E) { | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 9803 | return Success( | 
|  | 9804 | APFixedPoint(Value, Info.Ctx.getFixedPointSemantics(E->getType())), E); | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9805 | } | 
|  | 9806 |  | 
|  | 9807 | bool Success(const APValue &V, const Expr *E) { | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 9808 | return Success(V.getFixedPoint(), E); | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9809 | } | 
|  | 9810 |  | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 9811 | bool Success(const APFixedPoint &V, const Expr *E) { | 
|  | 9812 | assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); | 
|  | 9813 | assert(V.getWidth() == Info.Ctx.getIntWidth(E->getType()) && | 
|  | 9814 | "Invalid evaluation result."); | 
|  | 9815 | Result = APValue(V); | 
|  | 9816 | return true; | 
|  | 9817 | } | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9818 |  | 
|  | 9819 | //===--------------------------------------------------------------------===// | 
|  | 9820 | //                            Visitor Methods | 
|  | 9821 | //===--------------------------------------------------------------------===// | 
|  | 9822 |  | 
|  | 9823 | bool VisitFixedPointLiteral(const FixedPointLiteral *E) { | 
|  | 9824 | return Success(E->getValue(), E); | 
|  | 9825 | } | 
|  | 9826 |  | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 9827 | bool VisitCastExpr(const CastExpr *E); | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9828 | bool VisitUnaryOperator(const UnaryOperator *E); | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 9829 | bool VisitBinaryOperator(const BinaryOperator *E); | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 9830 | }; | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 9831 | } // end anonymous namespace | 
| Anders Carlsson | 4a3585b | 2008-07-08 15:34:11 +0000 | [diff] [blame] | 9832 |  | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 9833 | /// EvaluateIntegerOrLValue - Evaluate an rvalue integral-typed expression, and | 
|  | 9834 | /// produce either the integer value or a pointer. | 
|  | 9835 | /// | 
|  | 9836 | /// GCC has a heinous extension which folds casts between pointer types and | 
|  | 9837 | /// pointer-sized integral types. We support this by allowing the evaluation of | 
|  | 9838 | /// an integer rvalue to produce a pointer (represented as an lvalue) instead. | 
|  | 9839 | /// Some simple arithmetic on such values is supported (they are treated much | 
|  | 9840 | /// like char*). | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9841 | static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, | 
| Richard Smith | 0b0a0b6 | 2011-10-29 20:57:55 +0000 | [diff] [blame] | 9842 | EvalInfo &Info) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 9843 | assert(E->isRValue() && E->getType()->isIntegralOrEnumerationType()); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 9844 | return IntExprEvaluator(Info, Result).Visit(E); | 
| Daniel Dunbar | ce39954 | 2009-02-20 18:22:23 +0000 | [diff] [blame] | 9845 | } | 
| Daniel Dunbar | ca097ad | 2009-02-19 20:17:33 +0000 | [diff] [blame] | 9846 |  | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 9847 | static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) { | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 9848 | APValue Val; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 9849 | if (!EvaluateIntegerOrLValue(E, Val, Info)) | 
| Daniel Dunbar | ce39954 | 2009-02-20 18:22:23 +0000 | [diff] [blame] | 9850 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 9851 | if (!Val.isInt()) { | 
|  | 9852 | // FIXME: It would be better to produce the diagnostic for casting | 
|  | 9853 | //        a pointer to an integer. | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 9854 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 9855 | return false; | 
|  | 9856 | } | 
| Daniel Dunbar | ca097ad | 2009-02-19 20:17:33 +0000 | [diff] [blame] | 9857 | Result = Val.getInt(); | 
|  | 9858 | return true; | 
| Anders Carlsson | 4a3585b | 2008-07-08 15:34:11 +0000 | [diff] [blame] | 9859 | } | 
| Anders Carlsson | 4a3585b | 2008-07-08 15:34:11 +0000 | [diff] [blame] | 9860 |  | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 9861 | bool IntExprEvaluator::VisitSourceLocExpr(const SourceLocExpr *E) { | 
|  | 9862 | APValue Evaluated = E->EvaluateInContext( | 
|  | 9863 | Info.Ctx, Info.CurrentCall->CurSourceLocExprScope.getDefaultExpr()); | 
|  | 9864 | return Success(Evaluated, E); | 
|  | 9865 | } | 
|  | 9866 |  | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 9867 | static bool EvaluateFixedPoint(const Expr *E, APFixedPoint &Result, | 
|  | 9868 | EvalInfo &Info) { | 
|  | 9869 | if (E->getType()->isFixedPointType()) { | 
|  | 9870 | APValue Val; | 
|  | 9871 | if (!FixedPointExprEvaluator(Info, Val).Visit(E)) | 
|  | 9872 | return false; | 
|  | 9873 | if (!Val.isFixedPoint()) | 
|  | 9874 | return false; | 
|  | 9875 |  | 
|  | 9876 | Result = Val.getFixedPoint(); | 
|  | 9877 | return true; | 
|  | 9878 | } | 
|  | 9879 | return false; | 
|  | 9880 | } | 
|  | 9881 |  | 
|  | 9882 | static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result, | 
|  | 9883 | EvalInfo &Info) { | 
|  | 9884 | if (E->getType()->isIntegerType()) { | 
|  | 9885 | auto FXSema = Info.Ctx.getFixedPointSemantics(E->getType()); | 
|  | 9886 | APSInt Val; | 
|  | 9887 | if (!EvaluateInteger(E, Val, Info)) | 
|  | 9888 | return false; | 
|  | 9889 | Result = APFixedPoint(Val, FXSema); | 
|  | 9890 | return true; | 
|  | 9891 | } else if (E->getType()->isFixedPointType()) { | 
|  | 9892 | return EvaluateFixedPoint(E, Result, Info); | 
|  | 9893 | } | 
|  | 9894 | return false; | 
|  | 9895 | } | 
|  | 9896 |  | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 9897 | /// Check whether the given declaration can be directly converted to an integral | 
|  | 9898 | /// rvalue. If not, no diagnostic is produced; there are other things we can | 
|  | 9899 | /// try. | 
| Eli Friedman | fb8a93f | 2009-11-24 05:28:59 +0000 | [diff] [blame] | 9900 | bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { | 
| Chris Lattner | 7174bf3 | 2008-07-12 00:38:25 +0000 | [diff] [blame] | 9901 | // Enums are integer constant exprs. | 
| Abramo Bagnara | 2caedf4 | 2011-06-30 09:36:05 +0000 | [diff] [blame] | 9902 | if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) { | 
| Abramo Bagnara | 9ae292d | 2011-07-02 13:13:53 +0000 | [diff] [blame] | 9903 | // Check for signedness/width mismatches between E type and ECD value. | 
|  | 9904 | bool SameSign = (ECD->getInitVal().isSigned() | 
|  | 9905 | == E->getType()->isSignedIntegerOrEnumerationType()); | 
|  | 9906 | bool SameWidth = (ECD->getInitVal().getBitWidth() | 
|  | 9907 | == Info.Ctx.getIntWidth(E->getType())); | 
|  | 9908 | if (SameSign && SameWidth) | 
|  | 9909 | return Success(ECD->getInitVal(), E); | 
|  | 9910 | else { | 
|  | 9911 | // Get rid of mismatch (otherwise Success assertions will fail) | 
|  | 9912 | // by computing a new value matching the type of E. | 
|  | 9913 | llvm::APSInt Val = ECD->getInitVal(); | 
|  | 9914 | if (!SameSign) | 
|  | 9915 | Val.setIsSigned(!ECD->getInitVal().isSigned()); | 
|  | 9916 | if (!SameWidth) | 
|  | 9917 | Val = Val.extOrTrunc(Info.Ctx.getIntWidth(E->getType())); | 
|  | 9918 | return Success(Val, E); | 
|  | 9919 | } | 
| Abramo Bagnara | 2caedf4 | 2011-06-30 09:36:05 +0000 | [diff] [blame] | 9920 | } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 9921 | return false; | 
| Chris Lattner | 7174bf3 | 2008-07-12 00:38:25 +0000 | [diff] [blame] | 9922 | } | 
|  | 9923 |  | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9924 | /// Values returned by __builtin_classify_type, chosen to match the values | 
|  | 9925 | /// produced by GCC's builtin. | 
|  | 9926 | enum class GCCTypeClass { | 
|  | 9927 | None = -1, | 
|  | 9928 | Void = 0, | 
|  | 9929 | Integer = 1, | 
|  | 9930 | // GCC reserves 2 for character types, but instead classifies them as | 
|  | 9931 | // integers. | 
|  | 9932 | Enum = 3, | 
|  | 9933 | Bool = 4, | 
|  | 9934 | Pointer = 5, | 
|  | 9935 | // GCC reserves 6 for references, but appears to never use it (because | 
|  | 9936 | // expressions never have reference type, presumably). | 
|  | 9937 | PointerToDataMember = 7, | 
|  | 9938 | RealFloat = 8, | 
|  | 9939 | Complex = 9, | 
|  | 9940 | // GCC reserves 10 for functions, but does not use it since GCC version 6 due | 
|  | 9941 | // to decay to pointer. (Prior to version 6 it was only used in C++ mode). | 
|  | 9942 | // GCC claims to reserve 11 for pointers to member functions, but *actually* | 
|  | 9943 | // uses 12 for that purpose, same as for a class or struct. Maybe it | 
|  | 9944 | // internally implements a pointer to member as a struct?  Who knows. | 
|  | 9945 | PointerToMemberFunction = 12, // Not a bug, see above. | 
|  | 9946 | ClassOrStruct = 12, | 
|  | 9947 | Union = 13, | 
|  | 9948 | // GCC reserves 14 for arrays, but does not use it since GCC version 6 due to | 
|  | 9949 | // decay to pointer. (Prior to version 6 it was only used in C++ mode). | 
|  | 9950 | // GCC reserves 15 for strings, but actually uses 5 (pointer) for string | 
|  | 9951 | // literals. | 
|  | 9952 | }; | 
|  | 9953 |  | 
| Chris Lattner | 86ee286 | 2008-10-06 06:40:35 +0000 | [diff] [blame] | 9954 | /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way | 
|  | 9955 | /// as GCC. | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9956 | static GCCTypeClass | 
|  | 9957 | EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts) { | 
|  | 9958 | assert(!T->isDependentType() && "unexpected dependent type"); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 9959 |  | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9960 | QualType CanTy = T.getCanonicalType(); | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 9961 | const BuiltinType *BT = dyn_cast<BuiltinType>(CanTy); | 
|  | 9962 |  | 
|  | 9963 | switch (CanTy->getTypeClass()) { | 
|  | 9964 | #define TYPE(ID, BASE) | 
|  | 9965 | #define DEPENDENT_TYPE(ID, BASE) case Type::ID: | 
|  | 9966 | #define NON_CANONICAL_TYPE(ID, BASE) case Type::ID: | 
|  | 9967 | #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(ID, BASE) case Type::ID: | 
| John McCall | 36b12a8 | 2019-10-02 06:35:23 +0000 | [diff] [blame] | 9968 | #include "clang/AST/TypeNodes.inc" | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9969 | case Type::Auto: | 
|  | 9970 | case Type::DeducedTemplateSpecialization: | 
|  | 9971 | llvm_unreachable("unexpected non-canonical or dependent type"); | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 9972 |  | 
|  | 9973 | case Type::Builtin: | 
|  | 9974 | switch (BT->getKind()) { | 
|  | 9975 | #define BUILTIN_TYPE(ID, SINGLETON_ID) | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9976 | #define SIGNED_TYPE(ID, SINGLETON_ID) \ | 
|  | 9977 | case BuiltinType::ID: return GCCTypeClass::Integer; | 
|  | 9978 | #define FLOATING_TYPE(ID, SINGLETON_ID) \ | 
|  | 9979 | case BuiltinType::ID: return GCCTypeClass::RealFloat; | 
|  | 9980 | #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) \ | 
|  | 9981 | case BuiltinType::ID: break; | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 9982 | #include "clang/AST/BuiltinTypes.def" | 
|  | 9983 | case BuiltinType::Void: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9984 | return GCCTypeClass::Void; | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 9985 |  | 
|  | 9986 | case BuiltinType::Bool: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9987 | return GCCTypeClass::Bool; | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 9988 |  | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9989 | case BuiltinType::Char_U: | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 9990 | case BuiltinType::UChar: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 9991 | case BuiltinType::WChar_U: | 
|  | 9992 | case BuiltinType::Char8: | 
|  | 9993 | case BuiltinType::Char16: | 
|  | 9994 | case BuiltinType::Char32: | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 9995 | case BuiltinType::UShort: | 
|  | 9996 | case BuiltinType::UInt: | 
|  | 9997 | case BuiltinType::ULong: | 
|  | 9998 | case BuiltinType::ULongLong: | 
|  | 9999 | case BuiltinType::UInt128: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10000 | return GCCTypeClass::Integer; | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10001 |  | 
| Leonard Chan | f921d85 | 2018-06-04 16:07:52 +0000 | [diff] [blame] | 10002 | case BuiltinType::UShortAccum: | 
|  | 10003 | case BuiltinType::UAccum: | 
|  | 10004 | case BuiltinType::ULongAccum: | 
| Leonard Chan | ab80f3c | 2018-06-14 14:53:51 +0000 | [diff] [blame] | 10005 | case BuiltinType::UShortFract: | 
|  | 10006 | case BuiltinType::UFract: | 
|  | 10007 | case BuiltinType::ULongFract: | 
|  | 10008 | case BuiltinType::SatUShortAccum: | 
|  | 10009 | case BuiltinType::SatUAccum: | 
|  | 10010 | case BuiltinType::SatULongAccum: | 
|  | 10011 | case BuiltinType::SatUShortFract: | 
|  | 10012 | case BuiltinType::SatUFract: | 
|  | 10013 | case BuiltinType::SatULongFract: | 
| Leonard Chan | f921d85 | 2018-06-04 16:07:52 +0000 | [diff] [blame] | 10014 | return GCCTypeClass::None; | 
|  | 10015 |  | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10016 | case BuiltinType::NullPtr: | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10017 |  | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10018 | case BuiltinType::ObjCId: | 
|  | 10019 | case BuiltinType::ObjCClass: | 
|  | 10020 | case BuiltinType::ObjCSel: | 
| Alexey Bader | 954ba21 | 2016-04-08 13:40:33 +0000 | [diff] [blame] | 10021 | #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ | 
|  | 10022 | case BuiltinType::Id: | 
| Alexey Bader | b62f144 | 2016-04-13 08:33:41 +0000 | [diff] [blame] | 10023 | #include "clang/Basic/OpenCLImageTypes.def" | 
| Andrew Savonichev | 3fee351 | 2018-11-08 11:25:41 +0000 | [diff] [blame] | 10024 | #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ | 
|  | 10025 | case BuiltinType::Id: | 
|  | 10026 | #include "clang/Basic/OpenCLExtensionTypes.def" | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10027 | case BuiltinType::OCLSampler: | 
|  | 10028 | case BuiltinType::OCLEvent: | 
|  | 10029 | case BuiltinType::OCLClkEvent: | 
|  | 10030 | case BuiltinType::OCLQueue: | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10031 | case BuiltinType::OCLReserveID: | 
| Richard Sandiford | eb485fb | 2019-08-09 08:52:54 +0000 | [diff] [blame] | 10032 | #define SVE_TYPE(Name, Id, SingletonId) \ | 
|  | 10033 | case BuiltinType::Id: | 
|  | 10034 | #include "clang/Basic/AArch64SVEACLETypes.def" | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10035 | return GCCTypeClass::None; | 
|  | 10036 |  | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10037 | case BuiltinType::Dependent: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10038 | llvm_unreachable("unexpected dependent type"); | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10039 | }; | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10040 | llvm_unreachable("unexpected placeholder type"); | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10041 |  | 
|  | 10042 | case Type::Enum: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10043 | return LangOpts.CPlusPlus ? GCCTypeClass::Enum : GCCTypeClass::Integer; | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10044 |  | 
|  | 10045 | case Type::Pointer: | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10046 | case Type::ConstantArray: | 
|  | 10047 | case Type::VariableArray: | 
|  | 10048 | case Type::IncompleteArray: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10049 | case Type::FunctionNoProto: | 
|  | 10050 | case Type::FunctionProto: | 
|  | 10051 | return GCCTypeClass::Pointer; | 
|  | 10052 |  | 
|  | 10053 | case Type::MemberPointer: | 
|  | 10054 | return CanTy->isMemberDataPointerType() | 
|  | 10055 | ? GCCTypeClass::PointerToDataMember | 
|  | 10056 | : GCCTypeClass::PointerToMemberFunction; | 
|  | 10057 |  | 
|  | 10058 | case Type::Complex: | 
|  | 10059 | return GCCTypeClass::Complex; | 
|  | 10060 |  | 
|  | 10061 | case Type::Record: | 
|  | 10062 | return CanTy->isUnionType() ? GCCTypeClass::Union | 
|  | 10063 | : GCCTypeClass::ClassOrStruct; | 
|  | 10064 |  | 
|  | 10065 | case Type::Atomic: | 
|  | 10066 | // GCC classifies _Atomic T the same as T. | 
|  | 10067 | return EvaluateBuiltinClassifyType( | 
|  | 10068 | CanTy->castAs<AtomicType>()->getValueType(), LangOpts); | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10069 |  | 
|  | 10070 | case Type::BlockPointer: | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10071 | case Type::Vector: | 
|  | 10072 | case Type::ExtVector: | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10073 | case Type::ObjCObject: | 
|  | 10074 | case Type::ObjCInterface: | 
|  | 10075 | case Type::ObjCObjectPointer: | 
|  | 10076 | case Type::Pipe: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10077 | // GCC classifies vectors as None. We follow its lead and classify all | 
|  | 10078 | // other types that don't fit into the regular classification the same way. | 
|  | 10079 | return GCCTypeClass::None; | 
|  | 10080 |  | 
|  | 10081 | case Type::LValueReference: | 
|  | 10082 | case Type::RValueReference: | 
|  | 10083 | llvm_unreachable("invalid type for expression"); | 
| Andrey Bokhanko | 5f6588e | 2016-02-15 10:39:04 +0000 | [diff] [blame] | 10084 | } | 
|  | 10085 |  | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10086 | llvm_unreachable("unexpected type class"); | 
|  | 10087 | } | 
|  | 10088 |  | 
|  | 10089 | /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way | 
|  | 10090 | /// as GCC. | 
|  | 10091 | static GCCTypeClass | 
|  | 10092 | EvaluateBuiltinClassifyType(const CallExpr *E, const LangOptions &LangOpts) { | 
|  | 10093 | // If no argument was supplied, default to None. This isn't | 
|  | 10094 | // ideal, however it is what gcc does. | 
|  | 10095 | if (E->getNumArgs() == 0) | 
|  | 10096 | return GCCTypeClass::None; | 
|  | 10097 |  | 
|  | 10098 | // FIXME: Bizarrely, GCC treats a call with more than one argument as not | 
|  | 10099 | // being an ICE, but still folds it to a constant using the type of the first | 
|  | 10100 | // argument. | 
|  | 10101 | return EvaluateBuiltinClassifyType(E->getArg(0)->getType(), LangOpts); | 
| Chris Lattner | 86ee286 | 2008-10-06 06:40:35 +0000 | [diff] [blame] | 10102 | } | 
|  | 10103 |  | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 10104 | /// EvaluateBuiltinConstantPForLValue - Determine the result of | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10105 | /// __builtin_constant_p when applied to the given pointer. | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 10106 | /// | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10107 | /// A pointer is only "constant" if it is null (or a pointer cast to integer) | 
|  | 10108 | /// or it points to the first character of a string literal. | 
|  | 10109 | static bool EvaluateBuiltinConstantPForLValue(const APValue &LV) { | 
|  | 10110 | APValue::LValueBase Base = LV.getLValueBase(); | 
|  | 10111 | if (Base.isNull()) { | 
|  | 10112 | // A null base is acceptable. | 
|  | 10113 | return true; | 
|  | 10114 | } else if (const Expr *E = Base.dyn_cast<const Expr *>()) { | 
|  | 10115 | if (!isa<StringLiteral>(E)) | 
|  | 10116 | return false; | 
|  | 10117 | return LV.getLValueOffset().isZero(); | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 10118 | } else if (Base.is<TypeInfoLValue>()) { | 
|  | 10119 | // Surprisingly, GCC considers __builtin_constant_p(&typeid(int)) to | 
|  | 10120 | // evaluate to true. | 
|  | 10121 | return true; | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10122 | } else { | 
|  | 10123 | // Any other base is not constant enough for GCC. | 
|  | 10124 | return false; | 
|  | 10125 | } | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 10126 | } | 
|  | 10127 |  | 
|  | 10128 | /// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to | 
|  | 10129 | /// GCC as we can manage. | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10130 | static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) { | 
| Richard Smith | 37be336 | 2019-05-04 04:00:45 +0000 | [diff] [blame] | 10131 | // This evaluation is not permitted to have side-effects, so evaluate it in | 
|  | 10132 | // a speculative evaluation context. | 
|  | 10133 | SpeculativeEvaluationRAII SpeculativeEval(Info); | 
|  | 10134 |  | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10135 | // Constant-folding is always enabled for the operand of __builtin_constant_p | 
|  | 10136 | // (even when the enclosing evaluation context otherwise requires a strict | 
|  | 10137 | // language-specific constant expression). | 
|  | 10138 | FoldConstant Fold(Info, true); | 
|  | 10139 |  | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 10140 | QualType ArgType = Arg->getType(); | 
|  | 10141 |  | 
|  | 10142 | // __builtin_constant_p always has one operand. The rules which gcc follows | 
|  | 10143 | // are not precisely documented, but are as follows: | 
|  | 10144 | // | 
|  | 10145 | //  - If the operand is of integral, floating, complex or enumeration type, | 
|  | 10146 | //    and can be folded to a known value of that type, it returns 1. | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10147 | //  - If the operand can be folded to a pointer to the first character | 
|  | 10148 | //    of a string literal (or such a pointer cast to an integral type) | 
|  | 10149 | //    or to a null pointer or an integer cast to a pointer, it returns 1. | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 10150 | // | 
|  | 10151 | // Otherwise, it returns 0. | 
|  | 10152 | // | 
|  | 10153 | // FIXME: GCC also intends to return 1 for literals of aggregate types, but | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10154 | // its support for this did not work prior to GCC 9 and is not yet well | 
|  | 10155 | // understood. | 
|  | 10156 | if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() || | 
|  | 10157 | ArgType->isAnyComplexType() || ArgType->isPointerType() || | 
|  | 10158 | ArgType->isNullPtrType()) { | 
|  | 10159 | APValue V; | 
|  | 10160 | if (!::EvaluateAsRValue(Info, Arg, V)) { | 
|  | 10161 | Fold.keepDiagnostics(); | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 10162 | return false; | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10163 | } | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 10164 |  | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10165 | // For a pointer (possibly cast to integer), there are special rules. | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 10166 | if (V.getKind() == APValue::LValue) | 
|  | 10167 | return EvaluateBuiltinConstantPForLValue(V); | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10168 |  | 
|  | 10169 | // Otherwise, any constant value is good enough. | 
| Richard Smith | e637cbe | 2019-05-21 23:15:18 +0000 | [diff] [blame] | 10170 | return V.hasValue(); | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 10171 | } | 
|  | 10172 |  | 
|  | 10173 | // Anything else isn't considered to be sufficiently constant. | 
|  | 10174 | return false; | 
|  | 10175 | } | 
|  | 10176 |  | 
| John McCall | 9500760 | 2010-05-10 23:27:23 +0000 | [diff] [blame] | 10177 | /// Retrieves the "underlying object type" of the given expression, | 
|  | 10178 | /// as used by __builtin_object_size. | 
| George Burgess IV | bdb5b26 | 2015-08-19 02:19:07 +0000 | [diff] [blame] | 10179 | static QualType getObjectType(APValue::LValueBase B) { | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 10180 | if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) { | 
|  | 10181 | if (const VarDecl *VD = dyn_cast<VarDecl>(D)) | 
| John McCall | 9500760 | 2010-05-10 23:27:23 +0000 | [diff] [blame] | 10182 | return VD->getType(); | 
| Richard Smith | ce40ad6 | 2011-11-12 22:28:03 +0000 | [diff] [blame] | 10183 | } else if (const Expr *E = B.get<const Expr*>()) { | 
|  | 10184 | if (isa<CompoundLiteralExpr>(E)) | 
|  | 10185 | return E->getType(); | 
| Richard Smith | ee0ce302 | 2019-05-17 07:06:46 +0000 | [diff] [blame] | 10186 | } else if (B.is<TypeInfoLValue>()) { | 
|  | 10187 | return B.getTypeInfoType(); | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 10188 | } else if (B.is<DynamicAllocLValue>()) { | 
|  | 10189 | return B.getDynamicAllocType(); | 
| John McCall | 9500760 | 2010-05-10 23:27:23 +0000 | [diff] [blame] | 10190 | } | 
|  | 10191 |  | 
|  | 10192 | return QualType(); | 
|  | 10193 | } | 
|  | 10194 |  | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 10195 | /// A more selective version of E->IgnoreParenCasts for | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10196 | /// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only | 
| George Burgess IV | b40cd56 | 2015-09-04 22:36:18 +0000 | [diff] [blame] | 10197 | /// to change the type of E. | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 10198 | /// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo` | 
|  | 10199 | /// | 
|  | 10200 | /// Always returns an RValue with a pointer representation. | 
|  | 10201 | static const Expr *ignorePointerCastsAndParens(const Expr *E) { | 
|  | 10202 | assert(E->isRValue() && E->getType()->hasPointerRepresentation()); | 
|  | 10203 |  | 
|  | 10204 | auto *NoParens = E->IgnoreParens(); | 
|  | 10205 | auto *Cast = dyn_cast<CastExpr>(NoParens); | 
| George Burgess IV | b40cd56 | 2015-09-04 22:36:18 +0000 | [diff] [blame] | 10206 | if (Cast == nullptr) | 
|  | 10207 | return NoParens; | 
|  | 10208 |  | 
|  | 10209 | // We only conservatively allow a few kinds of casts, because this code is | 
|  | 10210 | // inherently a simple solution that seeks to support the common case. | 
|  | 10211 | auto CastKind = Cast->getCastKind(); | 
|  | 10212 | if (CastKind != CK_NoOp && CastKind != CK_BitCast && | 
|  | 10213 | CastKind != CK_AddressSpaceConversion) | 
| George Burgess IV | 3a03fab | 2015-09-04 21:28:13 +0000 | [diff] [blame] | 10214 | return NoParens; | 
|  | 10215 |  | 
|  | 10216 | auto *SubExpr = Cast->getSubExpr(); | 
|  | 10217 | if (!SubExpr->getType()->hasPointerRepresentation() || !SubExpr->isRValue()) | 
|  | 10218 | return NoParens; | 
|  | 10219 | return ignorePointerCastsAndParens(SubExpr); | 
|  | 10220 | } | 
|  | 10221 |  | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10222 | /// Checks to see if the given LValue's Designator is at the end of the LValue's | 
|  | 10223 | /// record layout. e.g. | 
|  | 10224 | ///   struct { struct { int a, b; } fst, snd; } obj; | 
|  | 10225 | ///   obj.fst   // no | 
|  | 10226 | ///   obj.snd   // yes | 
|  | 10227 | ///   obj.fst.a // no | 
|  | 10228 | ///   obj.fst.b // no | 
|  | 10229 | ///   obj.snd.a // no | 
|  | 10230 | ///   obj.snd.b // yes | 
|  | 10231 | /// | 
|  | 10232 | /// Please note: this function is specialized for how __builtin_object_size | 
|  | 10233 | /// views "objects". | 
| George Burgess IV | 4168d75 | 2016-06-27 19:40:41 +0000 | [diff] [blame] | 10234 | /// | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 10235 | /// If this encounters an invalid RecordDecl or otherwise cannot determine the | 
|  | 10236 | /// correct result, it will always return true. | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10237 | static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { | 
|  | 10238 | assert(!LVal.Designator.Invalid); | 
|  | 10239 |  | 
| George Burgess IV | 4168d75 | 2016-06-27 19:40:41 +0000 | [diff] [blame] | 10240 | auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD, bool &Invalid) { | 
|  | 10241 | const RecordDecl *Parent = FD->getParent(); | 
|  | 10242 | Invalid = Parent->isInvalidDecl(); | 
|  | 10243 | if (Invalid || Parent->isUnion()) | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10244 | return true; | 
| George Burgess IV | 4168d75 | 2016-06-27 19:40:41 +0000 | [diff] [blame] | 10245 | const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Parent); | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10246 | return FD->getFieldIndex() + 1 == Layout.getFieldCount(); | 
|  | 10247 | }; | 
|  | 10248 |  | 
|  | 10249 | auto &Base = LVal.getLValueBase(); | 
|  | 10250 | if (auto *ME = dyn_cast_or_null<MemberExpr>(Base.dyn_cast<const Expr *>())) { | 
|  | 10251 | if (auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) { | 
| George Burgess IV | 4168d75 | 2016-06-27 19:40:41 +0000 | [diff] [blame] | 10252 | bool Invalid; | 
|  | 10253 | if (!IsLastOrInvalidFieldDecl(FD, Invalid)) | 
|  | 10254 | return Invalid; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10255 | } else if (auto *IFD = dyn_cast<IndirectFieldDecl>(ME->getMemberDecl())) { | 
| George Burgess IV | 4168d75 | 2016-06-27 19:40:41 +0000 | [diff] [blame] | 10256 | for (auto *FD : IFD->chain()) { | 
|  | 10257 | bool Invalid; | 
|  | 10258 | if (!IsLastOrInvalidFieldDecl(cast<FieldDecl>(FD), Invalid)) | 
|  | 10259 | return Invalid; | 
|  | 10260 | } | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10261 | } | 
|  | 10262 | } | 
|  | 10263 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10264 | unsigned I = 0; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10265 | QualType BaseType = getType(Base); | 
| Daniel Jasper | ffdee09 | 2017-05-02 19:21:42 +0000 | [diff] [blame] | 10266 | if (LVal.Designator.FirstEntryIsAnUnsizedArray) { | 
| Richard Smith | 6f4f0f1 | 2017-10-20 22:56:25 +0000 | [diff] [blame] | 10267 | // If we don't know the array bound, conservatively assume we're looking at | 
|  | 10268 | // the final array element. | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10269 | ++I; | 
| Alex Lorenz | 4e24648 | 2017-12-20 21:03:38 +0000 | [diff] [blame] | 10270 | if (BaseType->isIncompleteArrayType()) | 
|  | 10271 | BaseType = Ctx.getAsArrayType(BaseType)->getElementType(); | 
|  | 10272 | else | 
|  | 10273 | BaseType = BaseType->castAs<PointerType>()->getPointeeType(); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10274 | } | 
|  | 10275 |  | 
|  | 10276 | for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) { | 
|  | 10277 | const auto &Entry = LVal.Designator.Entries[I]; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10278 | if (BaseType->isArrayType()) { | 
|  | 10279 | // Because __builtin_object_size treats arrays as objects, we can ignore | 
|  | 10280 | // the index iff this is the last array in the Designator. | 
|  | 10281 | if (I + 1 == E) | 
|  | 10282 | return true; | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10283 | const auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType)); | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 10284 | uint64_t Index = Entry.getAsArrayIndex(); | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10285 | if (Index + 1 != CAT->getSize()) | 
|  | 10286 | return false; | 
|  | 10287 | BaseType = CAT->getElementType(); | 
|  | 10288 | } else if (BaseType->isAnyComplexType()) { | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10289 | const auto *CT = BaseType->castAs<ComplexType>(); | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 10290 | uint64_t Index = Entry.getAsArrayIndex(); | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10291 | if (Index != 1) | 
|  | 10292 | return false; | 
|  | 10293 | BaseType = CT->getElementType(); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10294 | } else if (auto *FD = getAsField(Entry)) { | 
| George Burgess IV | 4168d75 | 2016-06-27 19:40:41 +0000 | [diff] [blame] | 10295 | bool Invalid; | 
|  | 10296 | if (!IsLastOrInvalidFieldDecl(FD, Invalid)) | 
|  | 10297 | return Invalid; | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10298 | BaseType = FD->getType(); | 
|  | 10299 | } else { | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10300 | assert(getAsBaseClass(Entry) && "Expecting cast to a base class"); | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10301 | return false; | 
|  | 10302 | } | 
|  | 10303 | } | 
|  | 10304 | return true; | 
|  | 10305 | } | 
|  | 10306 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10307 | /// Tests to see if the LValue has a user-specified designator (that isn't | 
|  | 10308 | /// necessarily valid). Note that this always returns 'true' if the LValue has | 
|  | 10309 | /// an unsized array as its first designator entry, because there's currently no | 
|  | 10310 | /// way to tell if the user typed *foo or foo[0]. | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10311 | static bool refersToCompleteObject(const LValue &LVal) { | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10312 | if (LVal.Designator.Invalid) | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10313 | return false; | 
|  | 10314 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10315 | if (!LVal.Designator.Entries.empty()) | 
|  | 10316 | return LVal.Designator.isMostDerivedAnUnsizedArray(); | 
|  | 10317 |  | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10318 | if (!LVal.InvalidBase) | 
|  | 10319 | return true; | 
|  | 10320 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10321 | // If `E` is a MemberExpr, then the first part of the designator is hiding in | 
|  | 10322 | // the LValueBase. | 
|  | 10323 | const auto *E = LVal.Base.dyn_cast<const Expr *>(); | 
|  | 10324 | return !E || !isa<MemberExpr>(E); | 
| George Burgess IV | a51c407 | 2015-10-16 01:49:01 +0000 | [diff] [blame] | 10325 | } | 
|  | 10326 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10327 | /// Attempts to detect a user writing into a piece of memory that's impossible | 
|  | 10328 | /// to figure out the size of by just using types. | 
|  | 10329 | static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) { | 
|  | 10330 | const SubobjectDesignator &Designator = LVal.Designator; | 
|  | 10331 | // Notes: | 
|  | 10332 | // - Users can only write off of the end when we have an invalid base. Invalid | 
|  | 10333 | //   bases imply we don't know where the memory came from. | 
|  | 10334 | // - We used to be a bit more aggressive here; we'd only be conservative if | 
|  | 10335 | //   the array at the end was flexible, or if it had 0 or 1 elements. This | 
|  | 10336 | //   broke some common standard library extensions (PR30346), but was | 
|  | 10337 | //   otherwise seemingly fine. It may be useful to reintroduce this behavior | 
|  | 10338 | //   with some sort of whitelist. OTOH, it seems that GCC is always | 
|  | 10339 | //   conservative with the last element in structs (if it's an array), so our | 
|  | 10340 | //   current behavior is more compatible than a whitelisting approach would | 
|  | 10341 | //   be. | 
|  | 10342 | return LVal.InvalidBase && | 
|  | 10343 | Designator.Entries.size() == Designator.MostDerivedPathLength && | 
|  | 10344 | Designator.MostDerivedIsArrayElement && | 
|  | 10345 | isDesignatorAtObjectEnd(Ctx, LVal); | 
|  | 10346 | } | 
|  | 10347 |  | 
|  | 10348 | /// Converts the given APInt to CharUnits, assuming the APInt is unsigned. | 
|  | 10349 | /// Fails if the conversion would cause loss of precision. | 
|  | 10350 | static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int, | 
|  | 10351 | CharUnits &Result) { | 
|  | 10352 | auto CharUnitsMax = std::numeric_limits<CharUnits::QuantityType>::max(); | 
|  | 10353 | if (Int.ugt(CharUnitsMax)) | 
|  | 10354 | return false; | 
|  | 10355 | Result = CharUnits::fromQuantity(Int.getZExtValue()); | 
|  | 10356 | return true; | 
|  | 10357 | } | 
|  | 10358 |  | 
|  | 10359 | /// Helper for tryEvaluateBuiltinObjectSize -- Given an LValue, this will | 
|  | 10360 | /// determine how many bytes exist from the beginning of the object to either | 
|  | 10361 | /// the end of the current subobject, or the end of the object itself, depending | 
|  | 10362 | /// on what the LValue looks like + the value of Type. | 
| George Burgess IV | a747027 | 2016-12-20 01:05:42 +0000 | [diff] [blame] | 10363 | /// | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10364 | /// If this returns false, the value of Result is undefined. | 
|  | 10365 | static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc, | 
|  | 10366 | unsigned Type, const LValue &LVal, | 
|  | 10367 | CharUnits &EndOffset) { | 
|  | 10368 | bool DetermineForCompleteObject = refersToCompleteObject(LVal); | 
| Chandler Carruth | d7738fe | 2016-12-20 08:28:19 +0000 | [diff] [blame] | 10369 |  | 
| George Burgess IV | 7fb7e36 | 2017-01-03 23:35:19 +0000 | [diff] [blame] | 10370 | auto CheckedHandleSizeof = [&](QualType Ty, CharUnits &Result) { | 
|  | 10371 | if (Ty.isNull() || Ty->isIncompleteType() || Ty->isFunctionType()) | 
|  | 10372 | return false; | 
|  | 10373 | return HandleSizeof(Info, ExprLoc, Ty, Result); | 
|  | 10374 | }; | 
|  | 10375 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10376 | // We want to evaluate the size of the entire object. This is a valid fallback | 
|  | 10377 | // for when Type=1 and the designator is invalid, because we're asked for an | 
|  | 10378 | // upper-bound. | 
|  | 10379 | if (!(Type & 1) || LVal.Designator.Invalid || DetermineForCompleteObject) { | 
|  | 10380 | // Type=3 wants a lower bound, so we can't fall back to this. | 
|  | 10381 | if (Type == 3 && !DetermineForCompleteObject) | 
| George Burgess IV | a747027 | 2016-12-20 01:05:42 +0000 | [diff] [blame] | 10382 | return false; | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10383 |  | 
|  | 10384 | llvm::APInt APEndOffset; | 
|  | 10385 | if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && | 
|  | 10386 | getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) | 
|  | 10387 | return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); | 
|  | 10388 |  | 
|  | 10389 | if (LVal.InvalidBase) | 
|  | 10390 | return false; | 
|  | 10391 |  | 
|  | 10392 | QualType BaseTy = getObjectType(LVal.getLValueBase()); | 
| George Burgess IV | 7fb7e36 | 2017-01-03 23:35:19 +0000 | [diff] [blame] | 10393 | return CheckedHandleSizeof(BaseTy, EndOffset); | 
| George Burgess IV | a747027 | 2016-12-20 01:05:42 +0000 | [diff] [blame] | 10394 | } | 
|  | 10395 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10396 | // We want to evaluate the size of a subobject. | 
|  | 10397 | const SubobjectDesignator &Designator = LVal.Designator; | 
| Chandler Carruth | d7738fe | 2016-12-20 08:28:19 +0000 | [diff] [blame] | 10398 |  | 
|  | 10399 | // The following is a moderately common idiom in C: | 
|  | 10400 | // | 
|  | 10401 | // struct Foo { int a; char c[1]; }; | 
|  | 10402 | // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); | 
|  | 10403 | // strcpy(&F->c[0], Bar); | 
|  | 10404 | // | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10405 | // In order to not break too much legacy code, we need to support it. | 
|  | 10406 | if (isUserWritingOffTheEnd(Info.Ctx, LVal)) { | 
|  | 10407 | // If we can resolve this to an alloc_size call, we can hand that back, | 
|  | 10408 | // because we know for certain how many bytes there are to write to. | 
|  | 10409 | llvm::APInt APEndOffset; | 
|  | 10410 | if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && | 
|  | 10411 | getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) | 
|  | 10412 | return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); | 
|  | 10413 |  | 
|  | 10414 | // If we cannot determine the size of the initial allocation, then we can't | 
|  | 10415 | // given an accurate upper-bound. However, we are still able to give | 
|  | 10416 | // conservative lower-bounds for Type=3. | 
|  | 10417 | if (Type == 1) | 
|  | 10418 | return false; | 
|  | 10419 | } | 
|  | 10420 |  | 
|  | 10421 | CharUnits BytesPerElem; | 
| George Burgess IV | 7fb7e36 | 2017-01-03 23:35:19 +0000 | [diff] [blame] | 10422 | if (!CheckedHandleSizeof(Designator.MostDerivedType, BytesPerElem)) | 
| Chandler Carruth | d7738fe | 2016-12-20 08:28:19 +0000 | [diff] [blame] | 10423 | return false; | 
|  | 10424 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10425 | // According to the GCC documentation, we want the size of the subobject | 
|  | 10426 | // denoted by the pointer. But that's not quite right -- what we actually | 
|  | 10427 | // want is the size of the immediately-enclosing array, if there is one. | 
|  | 10428 | int64_t ElemsRemaining; | 
|  | 10429 | if (Designator.MostDerivedIsArrayElement && | 
|  | 10430 | Designator.Entries.size() == Designator.MostDerivedPathLength) { | 
|  | 10431 | uint64_t ArraySize = Designator.getMostDerivedArraySize(); | 
| Richard Smith | 5b5e27a | 2019-05-10 20:05:31 +0000 | [diff] [blame] | 10432 | uint64_t ArrayIndex = Designator.Entries.back().getAsArrayIndex(); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10433 | ElemsRemaining = ArraySize <= ArrayIndex ? 0 : ArraySize - ArrayIndex; | 
|  | 10434 | } else { | 
|  | 10435 | ElemsRemaining = Designator.isOnePastTheEnd() ? 0 : 1; | 
|  | 10436 | } | 
| Chandler Carruth | d7738fe | 2016-12-20 08:28:19 +0000 | [diff] [blame] | 10437 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10438 | EndOffset = LVal.getLValueOffset() + BytesPerElem * ElemsRemaining; | 
|  | 10439 | return true; | 
| Chandler Carruth | d7738fe | 2016-12-20 08:28:19 +0000 | [diff] [blame] | 10440 | } | 
|  | 10441 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 10442 | /// Tries to evaluate the __builtin_object_size for @p E. If successful, | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10443 | /// returns true and stores the result in @p Size. | 
|  | 10444 | /// | 
|  | 10445 | /// If @p WasError is non-null, this will report whether the failure to evaluate | 
|  | 10446 | /// is to be treated as an Error in IntExprEvaluator. | 
|  | 10447 | static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, | 
|  | 10448 | EvalInfo &Info, uint64_t &Size) { | 
|  | 10449 | // Determine the denoted object. | 
|  | 10450 | LValue LVal; | 
|  | 10451 | { | 
|  | 10452 | // The operand of __builtin_object_size is never evaluated for side-effects. | 
|  | 10453 | // If there are any, but we can determine the pointed-to object anyway, then | 
|  | 10454 | // ignore the side-effects. | 
|  | 10455 | SpeculativeEvaluationRAII SpeculativeEval(Info); | 
| James Y Knight | 892b09b | 2018-10-10 02:53:43 +0000 | [diff] [blame] | 10456 | IgnoreSideEffectsRAII Fold(Info); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10457 |  | 
|  | 10458 | if (E->isGLValue()) { | 
|  | 10459 | // It's possible for us to be given GLValues if we're called via | 
|  | 10460 | // Expr::tryEvaluateObjectSize. | 
|  | 10461 | APValue RVal; | 
|  | 10462 | if (!EvaluateAsRValue(Info, E, RVal)) | 
|  | 10463 | return false; | 
|  | 10464 | LVal.setFrom(Info.Ctx, RVal); | 
| George Burgess IV | f9013bf | 2017-02-10 22:52:29 +0000 | [diff] [blame] | 10465 | } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info, | 
|  | 10466 | /*InvalidBaseOK=*/true)) | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10467 | return false; | 
|  | 10468 | } | 
|  | 10469 |  | 
|  | 10470 | // If we point to before the start of the object, there are no accessible | 
|  | 10471 | // bytes. | 
|  | 10472 | if (LVal.getLValueOffset().isNegative()) { | 
|  | 10473 | Size = 0; | 
|  | 10474 | return true; | 
|  | 10475 | } | 
|  | 10476 |  | 
|  | 10477 | CharUnits EndOffset; | 
|  | 10478 | if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset)) | 
|  | 10479 | return false; | 
|  | 10480 |  | 
|  | 10481 | // If we've fallen outside of the end offset, just pretend there's nothing to | 
|  | 10482 | // write to/read from. | 
|  | 10483 | if (EndOffset <= LVal.getLValueOffset()) | 
|  | 10484 | Size = 0; | 
|  | 10485 | else | 
|  | 10486 | Size = (EndOffset - LVal.getLValueOffset()).getQuantity(); | 
|  | 10487 | return true; | 
| John McCall | 9500760 | 2010-05-10 23:27:23 +0000 | [diff] [blame] | 10488 | } | 
|  | 10489 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 10490 | bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) { | 
|  | 10491 | llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true); | 
| Gauthier Harnisch | dea9d57 | 2019-06-21 08:26:21 +0000 | [diff] [blame] | 10492 | if (E->getResultAPValueKind() != APValue::None) | 
|  | 10493 | return Success(E->getAPValueResult(), E); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 10494 | return ExprEvaluatorBaseTy::VisitConstantExpr(E); | 
|  | 10495 | } | 
|  | 10496 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 10497 | bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { | 
| Richard Smith | 6328cbd | 2016-11-16 00:57:23 +0000 | [diff] [blame] | 10498 | if (unsigned BuiltinOp = E->getBuiltinCallee()) | 
|  | 10499 | return VisitBuiltinCallExpr(E, BuiltinOp); | 
|  | 10500 |  | 
|  | 10501 | return ExprEvaluatorBaseTy::VisitCallExpr(E); | 
|  | 10502 | } | 
|  | 10503 |  | 
|  | 10504 | bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, | 
|  | 10505 | unsigned BuiltinOp) { | 
| Alp Toker | a724cff | 2013-12-28 21:59:02 +0000 | [diff] [blame] | 10506 | switch (unsigned BuiltinOp = E->getBuiltinCallee()) { | 
| Chris Lattner | 4deaa4e | 2008-10-06 05:28:25 +0000 | [diff] [blame] | 10507 | default: | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 10508 | return ExprEvaluatorBaseTy::VisitCallExpr(E); | 
| Mike Stump | 722cedf | 2009-10-26 18:35:08 +0000 | [diff] [blame] | 10509 |  | 
| Erik Pilkington | 9c3b588 | 2019-01-30 20:34:53 +0000 | [diff] [blame] | 10510 | case Builtin::BI__builtin_dynamic_object_size: | 
| Mike Stump | 722cedf | 2009-10-26 18:35:08 +0000 | [diff] [blame] | 10511 | case Builtin::BI__builtin_object_size: { | 
| George Burgess IV | bdb5b26 | 2015-08-19 02:19:07 +0000 | [diff] [blame] | 10512 | // The type was checked when we built the expression. | 
|  | 10513 | unsigned Type = | 
|  | 10514 | E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); | 
|  | 10515 | assert(Type <= 3 && "unexpected type"); | 
|  | 10516 |  | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 10517 | uint64_t Size; | 
|  | 10518 | if (tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size)) | 
|  | 10519 | return Success(Size, E); | 
| Mike Stump | 722cedf | 2009-10-26 18:35:08 +0000 | [diff] [blame] | 10520 |  | 
| George Burgess IV | 3e3bb95b | 2015-12-02 21:58:08 +0000 | [diff] [blame] | 10521 | if (E->getArg(0)->HasSideEffects(Info.Ctx)) | 
| George Burgess IV | bdb5b26 | 2015-08-19 02:19:07 +0000 | [diff] [blame] | 10522 | return Success((Type & 2) ? 0 : -1, E); | 
| Mike Stump | 876387b | 2009-10-27 22:09:17 +0000 | [diff] [blame] | 10523 |  | 
| Richard Smith | 01ade17 | 2012-05-23 04:13:20 +0000 | [diff] [blame] | 10524 | // Expression had no side effects, but we couldn't statically determine the | 
|  | 10525 | // size of the referenced object. | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 10526 | switch (Info.EvalMode) { | 
|  | 10527 | case EvalInfo::EM_ConstantExpression: | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 10528 | case EvalInfo::EM_ConstantFold: | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 10529 | case EvalInfo::EM_IgnoreSideEffects: | 
| George Burgess IV | bdb5b26 | 2015-08-19 02:19:07 +0000 | [diff] [blame] | 10530 | // Leave it to IR generation. | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 10531 | return Error(E); | 
|  | 10532 | case EvalInfo::EM_ConstantExpressionUnevaluated: | 
| George Burgess IV | bdb5b26 | 2015-08-19 02:19:07 +0000 | [diff] [blame] | 10533 | // Reduce it to a constant now. | 
|  | 10534 | return Success((Type & 2) ? 0 : -1, E); | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 10535 | } | 
| Richard Smith | cb2ba5a | 2016-07-18 22:37:35 +0000 | [diff] [blame] | 10536 |  | 
|  | 10537 | llvm_unreachable("unexpected EvalMode"); | 
| Mike Stump | 722cedf | 2009-10-26 18:35:08 +0000 | [diff] [blame] | 10538 | } | 
|  | 10539 |  | 
| Tim Northover | 314fbfa | 2018-11-02 13:14:11 +0000 | [diff] [blame] | 10540 | case Builtin::BI__builtin_os_log_format_buffer_size: { | 
|  | 10541 | analyze_os_log::OSLogBufferLayout Layout; | 
|  | 10542 | analyze_os_log::computeOSLogBufferLayout(Info.Ctx, E, Layout); | 
|  | 10543 | return Success(Layout.size().getQuantity(), E); | 
|  | 10544 | } | 
|  | 10545 |  | 
| Benjamin Kramer | a801f4a | 2012-10-06 14:42:22 +0000 | [diff] [blame] | 10546 | case Builtin::BI__builtin_bswap16: | 
| Richard Smith | 80ac9ef | 2012-09-28 20:20:52 +0000 | [diff] [blame] | 10547 | case Builtin::BI__builtin_bswap32: | 
|  | 10548 | case Builtin::BI__builtin_bswap64: { | 
|  | 10549 | APSInt Val; | 
|  | 10550 | if (!EvaluateInteger(E->getArg(0), Val, Info)) | 
|  | 10551 | return false; | 
|  | 10552 |  | 
|  | 10553 | return Success(Val.byteSwap(), E); | 
|  | 10554 | } | 
|  | 10555 |  | 
| Richard Smith | 8889a3d | 2013-06-13 06:26:32 +0000 | [diff] [blame] | 10556 | case Builtin::BI__builtin_classify_type: | 
| Richard Smith | 08b682b | 2018-05-23 21:18:00 +0000 | [diff] [blame] | 10557 | return Success((int)EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E); | 
| Richard Smith | 8889a3d | 2013-06-13 06:26:32 +0000 | [diff] [blame] | 10558 |  | 
| Craig Topper | f95a6d9 | 2018-08-08 22:31:12 +0000 | [diff] [blame] | 10559 | case Builtin::BI__builtin_clrsb: | 
|  | 10560 | case Builtin::BI__builtin_clrsbl: | 
|  | 10561 | case Builtin::BI__builtin_clrsbll: { | 
|  | 10562 | APSInt Val; | 
|  | 10563 | if (!EvaluateInteger(E->getArg(0), Val, Info)) | 
|  | 10564 | return false; | 
|  | 10565 |  | 
|  | 10566 | return Success(Val.getBitWidth() - Val.getMinSignedBits(), E); | 
|  | 10567 | } | 
| Richard Smith | 8889a3d | 2013-06-13 06:26:32 +0000 | [diff] [blame] | 10568 |  | 
| Richard Smith | 80b3c8e | 2013-06-13 05:04:16 +0000 | [diff] [blame] | 10569 | case Builtin::BI__builtin_clz: | 
|  | 10570 | case Builtin::BI__builtin_clzl: | 
| Anders Carlsson | 1a9fe3d | 2014-07-07 15:53:44 +0000 | [diff] [blame] | 10571 | case Builtin::BI__builtin_clzll: | 
|  | 10572 | case Builtin::BI__builtin_clzs: { | 
| Richard Smith | 80b3c8e | 2013-06-13 05:04:16 +0000 | [diff] [blame] | 10573 | APSInt Val; | 
|  | 10574 | if (!EvaluateInteger(E->getArg(0), Val, Info)) | 
|  | 10575 | return false; | 
|  | 10576 | if (!Val) | 
|  | 10577 | return Error(E); | 
|  | 10578 |  | 
|  | 10579 | return Success(Val.countLeadingZeros(), E); | 
|  | 10580 | } | 
|  | 10581 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 10582 | case Builtin::BI__builtin_constant_p: { | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10583 | const Expr *Arg = E->getArg(0); | 
| David Blaikie | 639b3d1 | 2019-05-03 18:11:31 +0000 | [diff] [blame] | 10584 | if (EvaluateBuiltinConstantP(Info, Arg)) | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 10585 | return Success(true, E); | 
| David Blaikie | 639b3d1 | 2019-05-03 18:11:31 +0000 | [diff] [blame] | 10586 | if (Info.InConstantContext || Arg->HasSideEffects(Info.Ctx)) { | 
| Richard Smith | f7d3048 | 2019-05-02 23:21:28 +0000 | [diff] [blame] | 10587 | // Outside a constant context, eagerly evaluate to false in the presence | 
|  | 10588 | // of side-effects in order to avoid -Wunsequenced false-positives in | 
|  | 10589 | // a branch on __builtin_constant_p(expr). | 
| Richard Smith | 31cfb31 | 2019-04-27 02:58:17 +0000 | [diff] [blame] | 10590 | return Success(false, E); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 10591 | } | 
| David Blaikie | 639b3d1 | 2019-05-03 18:11:31 +0000 | [diff] [blame] | 10592 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
|  | 10593 | return false; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 10594 | } | 
| Richard Smith | 8889a3d | 2013-06-13 06:26:32 +0000 | [diff] [blame] | 10595 |  | 
| Dávid Bolvanský | b06305e | 2019-10-29 19:06:48 +0100 | [diff] [blame] | 10596 | case Builtin::BI__builtin_is_constant_evaluated: { | 
|  | 10597 | const auto *Callee = Info.CurrentCall->getCallee(); | 
|  | 10598 | if (Info.InConstantContext && !Info.CheckingPotentialConstantExpression && | 
|  | 10599 | (Info.CallStackDepth == 1 || | 
|  | 10600 | (Info.CallStackDepth == 2 && Callee->isInStdNamespace() && | 
|  | 10601 | Callee->getIdentifier() && | 
|  | 10602 | Callee->getIdentifier()->isStr("is_constant_evaluated")))) { | 
|  | 10603 | // FIXME: Find a better way to avoid duplicated diagnostics. | 
|  | 10604 | if (Info.EvalStatus.Diag) | 
|  | 10605 | Info.report((Info.CallStackDepth == 1) ? E->getExprLoc() | 
|  | 10606 | : Info.CurrentCall->CallLoc, | 
|  | 10607 | diag::warn_is_constant_evaluated_always_true_constexpr) | 
|  | 10608 | << (Info.CallStackDepth == 1 ? "__builtin_is_constant_evaluated" | 
|  | 10609 | : "std::is_constant_evaluated"); | 
|  | 10610 | } | 
|  | 10611 |  | 
| Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 10612 | return Success(Info.InConstantContext, E); | 
| Dávid Bolvanský | b06305e | 2019-10-29 19:06:48 +0100 | [diff] [blame] | 10613 | } | 
| Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 10614 |  | 
| Richard Smith | 80b3c8e | 2013-06-13 05:04:16 +0000 | [diff] [blame] | 10615 | case Builtin::BI__builtin_ctz: | 
|  | 10616 | case Builtin::BI__builtin_ctzl: | 
| Anders Carlsson | 1a9fe3d | 2014-07-07 15:53:44 +0000 | [diff] [blame] | 10617 | case Builtin::BI__builtin_ctzll: | 
|  | 10618 | case Builtin::BI__builtin_ctzs: { | 
| Richard Smith | 80b3c8e | 2013-06-13 05:04:16 +0000 | [diff] [blame] | 10619 | APSInt Val; | 
|  | 10620 | if (!EvaluateInteger(E->getArg(0), Val, Info)) | 
|  | 10621 | return false; | 
|  | 10622 | if (!Val) | 
|  | 10623 | return Error(E); | 
|  | 10624 |  | 
|  | 10625 | return Success(Val.countTrailingZeros(), E); | 
|  | 10626 | } | 
|  | 10627 |  | 
| Richard Smith | 8889a3d | 2013-06-13 06:26:32 +0000 | [diff] [blame] | 10628 | case Builtin::BI__builtin_eh_return_data_regno: { | 
|  | 10629 | int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); | 
|  | 10630 | Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand); | 
|  | 10631 | return Success(Operand, E); | 
|  | 10632 | } | 
|  | 10633 |  | 
|  | 10634 | case Builtin::BI__builtin_expect: | 
|  | 10635 | return Visit(E->getArg(0)); | 
|  | 10636 |  | 
|  | 10637 | case Builtin::BI__builtin_ffs: | 
|  | 10638 | case Builtin::BI__builtin_ffsl: | 
|  | 10639 | case Builtin::BI__builtin_ffsll: { | 
|  | 10640 | APSInt Val; | 
|  | 10641 | if (!EvaluateInteger(E->getArg(0), Val, Info)) | 
|  | 10642 | return false; | 
|  | 10643 |  | 
|  | 10644 | unsigned N = Val.countTrailingZeros(); | 
|  | 10645 | return Success(N == Val.getBitWidth() ? 0 : N + 1, E); | 
|  | 10646 | } | 
|  | 10647 |  | 
|  | 10648 | case Builtin::BI__builtin_fpclassify: { | 
|  | 10649 | APFloat Val(0.0); | 
|  | 10650 | if (!EvaluateFloat(E->getArg(5), Val, Info)) | 
|  | 10651 | return false; | 
|  | 10652 | unsigned Arg; | 
|  | 10653 | switch (Val.getCategory()) { | 
|  | 10654 | case APFloat::fcNaN: Arg = 0; break; | 
|  | 10655 | case APFloat::fcInfinity: Arg = 1; break; | 
|  | 10656 | case APFloat::fcNormal: Arg = Val.isDenormal() ? 3 : 2; break; | 
|  | 10657 | case APFloat::fcZero: Arg = 4; break; | 
|  | 10658 | } | 
|  | 10659 | return Visit(E->getArg(Arg)); | 
|  | 10660 | } | 
|  | 10661 |  | 
|  | 10662 | case Builtin::BI__builtin_isinf_sign: { | 
|  | 10663 | APFloat Val(0.0); | 
| Richard Smith | ab341c6 | 2013-06-13 06:31:13 +0000 | [diff] [blame] | 10664 | return EvaluateFloat(E->getArg(0), Val, Info) && | 
| Richard Smith | 8889a3d | 2013-06-13 06:26:32 +0000 | [diff] [blame] | 10665 | Success(Val.isInfinity() ? (Val.isNegative() ? -1 : 1) : 0, E); | 
|  | 10666 | } | 
|  | 10667 |  | 
| Richard Smith | ea3019d | 2013-10-15 19:07:14 +0000 | [diff] [blame] | 10668 | case Builtin::BI__builtin_isinf: { | 
|  | 10669 | APFloat Val(0.0); | 
|  | 10670 | return EvaluateFloat(E->getArg(0), Val, Info) && | 
|  | 10671 | Success(Val.isInfinity() ? 1 : 0, E); | 
|  | 10672 | } | 
|  | 10673 |  | 
|  | 10674 | case Builtin::BI__builtin_isfinite: { | 
|  | 10675 | APFloat Val(0.0); | 
|  | 10676 | return EvaluateFloat(E->getArg(0), Val, Info) && | 
|  | 10677 | Success(Val.isFinite() ? 1 : 0, E); | 
|  | 10678 | } | 
|  | 10679 |  | 
|  | 10680 | case Builtin::BI__builtin_isnan: { | 
|  | 10681 | APFloat Val(0.0); | 
|  | 10682 | return EvaluateFloat(E->getArg(0), Val, Info) && | 
|  | 10683 | Success(Val.isNaN() ? 1 : 0, E); | 
|  | 10684 | } | 
|  | 10685 |  | 
|  | 10686 | case Builtin::BI__builtin_isnormal: { | 
|  | 10687 | APFloat Val(0.0); | 
|  | 10688 | return EvaluateFloat(E->getArg(0), Val, Info) && | 
|  | 10689 | Success(Val.isNormal() ? 1 : 0, E); | 
|  | 10690 | } | 
|  | 10691 |  | 
| Richard Smith | 8889a3d | 2013-06-13 06:26:32 +0000 | [diff] [blame] | 10692 | case Builtin::BI__builtin_parity: | 
|  | 10693 | case Builtin::BI__builtin_parityl: | 
|  | 10694 | case Builtin::BI__builtin_parityll: { | 
|  | 10695 | APSInt Val; | 
|  | 10696 | if (!EvaluateInteger(E->getArg(0), Val, Info)) | 
|  | 10697 | return false; | 
|  | 10698 |  | 
|  | 10699 | return Success(Val.countPopulation() % 2, E); | 
|  | 10700 | } | 
|  | 10701 |  | 
| Richard Smith | 80b3c8e | 2013-06-13 05:04:16 +0000 | [diff] [blame] | 10702 | case Builtin::BI__builtin_popcount: | 
|  | 10703 | case Builtin::BI__builtin_popcountl: | 
|  | 10704 | case Builtin::BI__builtin_popcountll: { | 
|  | 10705 | APSInt Val; | 
|  | 10706 | if (!EvaluateInteger(E->getArg(0), Val, Info)) | 
|  | 10707 | return false; | 
|  | 10708 |  | 
|  | 10709 | return Success(Val.countPopulation(), E); | 
|  | 10710 | } | 
|  | 10711 |  | 
| Douglas Gregor | 6a6dac2 | 2010-09-10 06:27:15 +0000 | [diff] [blame] | 10712 | case Builtin::BIstrlen: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10713 | case Builtin::BIwcslen: | 
| Richard Smith | 9cf080f | 2012-01-18 03:06:12 +0000 | [diff] [blame] | 10714 | // A call to strlen is not a constant expression. | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 10715 | if (Info.getLangOpts().CPlusPlus11) | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 10716 | Info.CCEDiag(E, diag::note_constexpr_invalid_function) | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10717 | << /*isConstexpr*/0 << /*isConstructor*/0 | 
|  | 10718 | << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); | 
| Richard Smith | 9cf080f | 2012-01-18 03:06:12 +0000 | [diff] [blame] | 10719 | else | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 10720 | Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Adrian Prantl | f3b3ccd | 2017-12-19 22:06:11 +0000 | [diff] [blame] | 10721 | LLVM_FALLTHROUGH; | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10722 | case Builtin::BI__builtin_strlen: | 
|  | 10723 | case Builtin::BI__builtin_wcslen: { | 
| Richard Smith | e6c19f2 | 2013-11-15 02:10:04 +0000 | [diff] [blame] | 10724 | // As an extension, we support __builtin_strlen() as a constant expression, | 
|  | 10725 | // and support folding strlen() to a constant. | 
|  | 10726 | LValue String; | 
|  | 10727 | if (!EvaluatePointer(E->getArg(0), String, Info)) | 
|  | 10728 | return false; | 
|  | 10729 |  | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10730 | QualType CharTy = E->getArg(0)->getType()->getPointeeType(); | 
|  | 10731 |  | 
| Richard Smith | e6c19f2 | 2013-11-15 02:10:04 +0000 | [diff] [blame] | 10732 | // Fast path: if it's a string literal, search the string value. | 
|  | 10733 | if (const StringLiteral *S = dyn_cast_or_null<StringLiteral>( | 
|  | 10734 | String.getLValueBase().dyn_cast<const Expr *>())) { | 
| Douglas Gregor | 6a6dac2 | 2010-09-10 06:27:15 +0000 | [diff] [blame] | 10735 | // The string literal may have embedded null characters. Find the first | 
|  | 10736 | // one and truncate there. | 
| Richard Smith | e6c19f2 | 2013-11-15 02:10:04 +0000 | [diff] [blame] | 10737 | StringRef Str = S->getBytes(); | 
|  | 10738 | int64_t Off = String.Offset.getQuantity(); | 
|  | 10739 | if (Off >= 0 && (uint64_t)Off <= (uint64_t)Str.size() && | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10740 | S->getCharByteWidth() == 1 && | 
|  | 10741 | // FIXME: Add fast-path for wchar_t too. | 
|  | 10742 | Info.Ctx.hasSameUnqualifiedType(CharTy, Info.Ctx.CharTy)) { | 
| Richard Smith | e6c19f2 | 2013-11-15 02:10:04 +0000 | [diff] [blame] | 10743 | Str = Str.substr(Off); | 
|  | 10744 |  | 
|  | 10745 | StringRef::size_type Pos = Str.find(0); | 
|  | 10746 | if (Pos != StringRef::npos) | 
|  | 10747 | Str = Str.substr(0, Pos); | 
|  | 10748 |  | 
|  | 10749 | return Success(Str.size(), E); | 
|  | 10750 | } | 
|  | 10751 |  | 
|  | 10752 | // Fall through to slow path to issue appropriate diagnostic. | 
| Douglas Gregor | 6a6dac2 | 2010-09-10 06:27:15 +0000 | [diff] [blame] | 10753 | } | 
| Richard Smith | e6c19f2 | 2013-11-15 02:10:04 +0000 | [diff] [blame] | 10754 |  | 
|  | 10755 | // Slow path: scan the bytes of the string looking for the terminating 0. | 
| Richard Smith | e6c19f2 | 2013-11-15 02:10:04 +0000 | [diff] [blame] | 10756 | for (uint64_t Strlen = 0; /**/; ++Strlen) { | 
|  | 10757 | APValue Char; | 
|  | 10758 | if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) || | 
|  | 10759 | !Char.isInt()) | 
|  | 10760 | return false; | 
|  | 10761 | if (!Char.getInt()) | 
|  | 10762 | return Success(Strlen, E); | 
|  | 10763 | if (!HandleLValueArrayAdjustment(Info, E, String, CharTy, 1)) | 
|  | 10764 | return false; | 
|  | 10765 | } | 
|  | 10766 | } | 
| Eli Friedman | a4c2602 | 2011-10-17 21:44:23 +0000 | [diff] [blame] | 10767 |  | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10768 | case Builtin::BIstrcmp: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10769 | case Builtin::BIwcscmp: | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10770 | case Builtin::BIstrncmp: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10771 | case Builtin::BIwcsncmp: | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10772 | case Builtin::BImemcmp: | 
| Clement Courbet | 8c3343d | 2019-02-14 12:00:34 +0000 | [diff] [blame] | 10773 | case Builtin::BIbcmp: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10774 | case Builtin::BIwmemcmp: | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10775 | // A call to strlen is not a constant expression. | 
|  | 10776 | if (Info.getLangOpts().CPlusPlus11) | 
|  | 10777 | Info.CCEDiag(E, diag::note_constexpr_invalid_function) | 
|  | 10778 | << /*isConstexpr*/0 << /*isConstructor*/0 | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10779 | << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10780 | else | 
|  | 10781 | Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Adrian Prantl | f3b3ccd | 2017-12-19 22:06:11 +0000 | [diff] [blame] | 10782 | LLVM_FALLTHROUGH; | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10783 | case Builtin::BI__builtin_strcmp: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10784 | case Builtin::BI__builtin_wcscmp: | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10785 | case Builtin::BI__builtin_strncmp: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10786 | case Builtin::BI__builtin_wcsncmp: | 
|  | 10787 | case Builtin::BI__builtin_memcmp: | 
| Clement Courbet | 8c3343d | 2019-02-14 12:00:34 +0000 | [diff] [blame] | 10788 | case Builtin::BI__builtin_bcmp: | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10789 | case Builtin::BI__builtin_wmemcmp: { | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10790 | LValue String1, String2; | 
|  | 10791 | if (!EvaluatePointer(E->getArg(0), String1, Info) || | 
|  | 10792 | !EvaluatePointer(E->getArg(1), String2, Info)) | 
|  | 10793 | return false; | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10794 |  | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10795 | uint64_t MaxLength = uint64_t(-1); | 
|  | 10796 | if (BuiltinOp != Builtin::BIstrcmp && | 
| Richard Smith | 8110c9d | 2016-11-29 19:45:17 +0000 | [diff] [blame] | 10797 | BuiltinOp != Builtin::BIwcscmp && | 
|  | 10798 | BuiltinOp != Builtin::BI__builtin_strcmp && | 
|  | 10799 | BuiltinOp != Builtin::BI__builtin_wcscmp) { | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10800 | APSInt N; | 
|  | 10801 | if (!EvaluateInteger(E->getArg(2), N, Info)) | 
|  | 10802 | return false; | 
|  | 10803 | MaxLength = N.getExtValue(); | 
|  | 10804 | } | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 10805 |  | 
|  | 10806 | // Empty substrings compare equal by definition. | 
|  | 10807 | if (MaxLength == 0u) | 
|  | 10808 | return Success(0, E); | 
|  | 10809 |  | 
|  | 10810 | if (!String1.checkNullPointerForFoldAccess(Info, E, AK_Read) || | 
|  | 10811 | !String2.checkNullPointerForFoldAccess(Info, E, AK_Read) || | 
|  | 10812 | String1.Designator.Invalid || String2.Designator.Invalid) | 
|  | 10813 | return false; | 
|  | 10814 |  | 
|  | 10815 | QualType CharTy1 = String1.Designator.getType(Info.Ctx); | 
|  | 10816 | QualType CharTy2 = String2.Designator.getType(Info.Ctx); | 
|  | 10817 |  | 
|  | 10818 | bool IsRawByte = BuiltinOp == Builtin::BImemcmp || | 
| Clement Courbet | 8c3343d | 2019-02-14 12:00:34 +0000 | [diff] [blame] | 10819 | BuiltinOp == Builtin::BIbcmp || | 
|  | 10820 | BuiltinOp == Builtin::BI__builtin_memcmp || | 
|  | 10821 | BuiltinOp == Builtin::BI__builtin_bcmp; | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 10822 |  | 
|  | 10823 | assert(IsRawByte || | 
|  | 10824 | (Info.Ctx.hasSameUnqualifiedType( | 
|  | 10825 | CharTy1, E->getArg(0)->getType()->getPointeeType()) && | 
|  | 10826 | Info.Ctx.hasSameUnqualifiedType(CharTy1, CharTy2))); | 
|  | 10827 |  | 
|  | 10828 | const auto &ReadCurElems = [&](APValue &Char1, APValue &Char2) { | 
|  | 10829 | return handleLValueToRValueConversion(Info, E, CharTy1, String1, Char1) && | 
|  | 10830 | handleLValueToRValueConversion(Info, E, CharTy2, String2, Char2) && | 
|  | 10831 | Char1.isInt() && Char2.isInt(); | 
|  | 10832 | }; | 
|  | 10833 | const auto &AdvanceElems = [&] { | 
|  | 10834 | return HandleLValueArrayAdjustment(Info, E, String1, CharTy1, 1) && | 
|  | 10835 | HandleLValueArrayAdjustment(Info, E, String2, CharTy2, 1); | 
|  | 10836 | }; | 
|  | 10837 |  | 
|  | 10838 | if (IsRawByte) { | 
|  | 10839 | uint64_t BytesRemaining = MaxLength; | 
|  | 10840 | // Pointers to const void may point to objects of incomplete type. | 
|  | 10841 | if (CharTy1->isIncompleteType()) { | 
|  | 10842 | Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy1; | 
|  | 10843 | return false; | 
|  | 10844 | } | 
|  | 10845 | if (CharTy2->isIncompleteType()) { | 
|  | 10846 | Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << CharTy2; | 
|  | 10847 | return false; | 
|  | 10848 | } | 
|  | 10849 | uint64_t CharTy1Width{Info.Ctx.getTypeSize(CharTy1)}; | 
|  | 10850 | CharUnits CharTy1Size = Info.Ctx.toCharUnitsFromBits(CharTy1Width); | 
|  | 10851 | // Give up on comparing between elements with disparate widths. | 
|  | 10852 | if (CharTy1Size != Info.Ctx.getTypeSizeInChars(CharTy2)) | 
|  | 10853 | return false; | 
|  | 10854 | uint64_t BytesPerElement = CharTy1Size.getQuantity(); | 
|  | 10855 | assert(BytesRemaining && "BytesRemaining should not be zero: the " | 
|  | 10856 | "following loop considers at least one element"); | 
|  | 10857 | while (true) { | 
|  | 10858 | APValue Char1, Char2; | 
|  | 10859 | if (!ReadCurElems(Char1, Char2)) | 
|  | 10860 | return false; | 
|  | 10861 | // We have compatible in-memory widths, but a possible type and | 
|  | 10862 | // (for `bool`) internal representation mismatch. | 
|  | 10863 | // Assuming two's complement representation, including 0 for `false` and | 
|  | 10864 | // 1 for `true`, we can check an appropriate number of elements for | 
|  | 10865 | // equality even if they are not byte-sized. | 
|  | 10866 | APSInt Char1InMem = Char1.getInt().extOrTrunc(CharTy1Width); | 
|  | 10867 | APSInt Char2InMem = Char2.getInt().extOrTrunc(CharTy1Width); | 
|  | 10868 | if (Char1InMem.ne(Char2InMem)) { | 
|  | 10869 | // If the elements are byte-sized, then we can produce a three-way | 
|  | 10870 | // comparison result in a straightforward manner. | 
|  | 10871 | if (BytesPerElement == 1u) { | 
|  | 10872 | // memcmp always compares unsigned chars. | 
|  | 10873 | return Success(Char1InMem.ult(Char2InMem) ? -1 : 1, E); | 
|  | 10874 | } | 
|  | 10875 | // The result is byte-order sensitive, and we have multibyte elements. | 
|  | 10876 | // FIXME: We can compare the remaining bytes in the correct order. | 
|  | 10877 | return false; | 
|  | 10878 | } | 
|  | 10879 | if (!AdvanceElems()) | 
|  | 10880 | return false; | 
|  | 10881 | if (BytesRemaining <= BytesPerElement) | 
|  | 10882 | break; | 
|  | 10883 | BytesRemaining -= BytesPerElement; | 
|  | 10884 | } | 
|  | 10885 | // Enough elements are equal to account for the memcmp limit. | 
|  | 10886 | return Success(0, E); | 
|  | 10887 | } | 
|  | 10888 |  | 
| Clement Courbet | 8c3343d | 2019-02-14 12:00:34 +0000 | [diff] [blame] | 10889 | bool StopAtNull = | 
|  | 10890 | (BuiltinOp != Builtin::BImemcmp && BuiltinOp != Builtin::BIbcmp && | 
|  | 10891 | BuiltinOp != Builtin::BIwmemcmp && | 
|  | 10892 | BuiltinOp != Builtin::BI__builtin_memcmp && | 
|  | 10893 | BuiltinOp != Builtin::BI__builtin_bcmp && | 
|  | 10894 | BuiltinOp != Builtin::BI__builtin_wmemcmp); | 
| Benjamin Kramer | 33b7092 | 2018-04-23 22:04:34 +0000 | [diff] [blame] | 10895 | bool IsWide = BuiltinOp == Builtin::BIwcscmp || | 
|  | 10896 | BuiltinOp == Builtin::BIwcsncmp || | 
|  | 10897 | BuiltinOp == Builtin::BIwmemcmp || | 
|  | 10898 | BuiltinOp == Builtin::BI__builtin_wcscmp || | 
|  | 10899 | BuiltinOp == Builtin::BI__builtin_wcsncmp || | 
|  | 10900 | BuiltinOp == Builtin::BI__builtin_wmemcmp; | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 10901 |  | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10902 | for (; MaxLength; --MaxLength) { | 
|  | 10903 | APValue Char1, Char2; | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 10904 | if (!ReadCurElems(Char1, Char2)) | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10905 | return false; | 
| Benjamin Kramer | 33b7092 | 2018-04-23 22:04:34 +0000 | [diff] [blame] | 10906 | if (Char1.getInt() != Char2.getInt()) { | 
|  | 10907 | if (IsWide) // wmemcmp compares with wchar_t signedness. | 
|  | 10908 | return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E); | 
|  | 10909 | // memcmp always compares unsigned chars. | 
|  | 10910 | return Success(Char1.getInt().ult(Char2.getInt()) ? -1 : 1, E); | 
|  | 10911 | } | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10912 | if (StopAtNull && !Char1.getInt()) | 
|  | 10913 | return Success(0, E); | 
|  | 10914 | assert(!(StopAtNull && !Char2.getInt())); | 
| Hubert Tong | 147b743 | 2018-12-12 16:53:43 +0000 | [diff] [blame] | 10915 | if (!AdvanceElems()) | 
| Richard Smith | e151bab | 2016-11-11 23:43:35 +0000 | [diff] [blame] | 10916 | return false; | 
|  | 10917 | } | 
|  | 10918 | // We hit the strncmp / memcmp limit. | 
|  | 10919 | return Success(0, E); | 
|  | 10920 | } | 
|  | 10921 |  | 
| Richard Smith | 01ba47d | 2012-04-13 00:45:38 +0000 | [diff] [blame] | 10922 | case Builtin::BI__atomic_always_lock_free: | 
| Richard Smith | b1e36c6 | 2012-04-11 17:55:32 +0000 | [diff] [blame] | 10923 | case Builtin::BI__atomic_is_lock_free: | 
|  | 10924 | case Builtin::BI__c11_atomic_is_lock_free: { | 
| Eli Friedman | a4c2602 | 2011-10-17 21:44:23 +0000 | [diff] [blame] | 10925 | APSInt SizeVal; | 
|  | 10926 | if (!EvaluateInteger(E->getArg(0), SizeVal, Info)) | 
|  | 10927 | return false; | 
|  | 10928 |  | 
|  | 10929 | // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power | 
|  | 10930 | // of two less than the maximum inline atomic width, we know it is | 
|  | 10931 | // lock-free.  If the size isn't a power of two, or greater than the | 
|  | 10932 | // maximum alignment where we promote atomics, we know it is not lock-free | 
|  | 10933 | // (at least not in the sense of atomic_is_lock_free).  Otherwise, | 
|  | 10934 | // the answer can only be determined at runtime; for example, 16-byte | 
|  | 10935 | // atomics have lock-free implementations on some, but not all, | 
|  | 10936 | // x86-64 processors. | 
|  | 10937 |  | 
|  | 10938 | // Check power-of-two. | 
|  | 10939 | CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue()); | 
| Richard Smith | 01ba47d | 2012-04-13 00:45:38 +0000 | [diff] [blame] | 10940 | if (Size.isPowerOfTwo()) { | 
|  | 10941 | // Check against inlining width. | 
|  | 10942 | unsigned InlineWidthBits = | 
|  | 10943 | Info.Ctx.getTargetInfo().getMaxAtomicInlineWidth(); | 
|  | 10944 | if (Size <= Info.Ctx.toCharUnitsFromBits(InlineWidthBits)) { | 
|  | 10945 | if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free || | 
|  | 10946 | Size == CharUnits::One() || | 
|  | 10947 | E->getArg(1)->isNullPointerConstant(Info.Ctx, | 
|  | 10948 | Expr::NPC_NeverValueDependent)) | 
|  | 10949 | // OK, we will inline appropriately-aligned operations of this size, | 
|  | 10950 | // and _Atomic(T) is appropriately-aligned. | 
|  | 10951 | return Success(1, E); | 
| Eli Friedman | a4c2602 | 2011-10-17 21:44:23 +0000 | [diff] [blame] | 10952 |  | 
| Richard Smith | 01ba47d | 2012-04-13 00:45:38 +0000 | [diff] [blame] | 10953 | QualType PointeeType = E->getArg(1)->IgnoreImpCasts()->getType()-> | 
|  | 10954 | castAs<PointerType>()->getPointeeType(); | 
|  | 10955 | if (!PointeeType->isIncompleteType() && | 
|  | 10956 | Info.Ctx.getTypeAlignInChars(PointeeType) >= Size) { | 
|  | 10957 | // OK, we will inline operations on this object. | 
|  | 10958 | return Success(1, E); | 
|  | 10959 | } | 
|  | 10960 | } | 
|  | 10961 | } | 
| Eli Friedman | a4c2602 | 2011-10-17 21:44:23 +0000 | [diff] [blame] | 10962 |  | 
| Richard Smith | 01ba47d | 2012-04-13 00:45:38 +0000 | [diff] [blame] | 10963 | return BuiltinOp == Builtin::BI__atomic_always_lock_free ? | 
|  | 10964 | Success(0, E) : Error(E); | 
| Eli Friedman | a4c2602 | 2011-10-17 21:44:23 +0000 | [diff] [blame] | 10965 | } | 
| Jonas Hahnfeld | 23604a8 | 2017-10-17 14:28:14 +0000 | [diff] [blame] | 10966 | case Builtin::BIomp_is_initial_device: | 
|  | 10967 | // We can decide statically which value the runtime would return if called. | 
|  | 10968 | return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E); | 
| Erich Keane | 0095827 | 2018-06-13 20:43:27 +0000 | [diff] [blame] | 10969 | case Builtin::BI__builtin_add_overflow: | 
|  | 10970 | case Builtin::BI__builtin_sub_overflow: | 
|  | 10971 | case Builtin::BI__builtin_mul_overflow: | 
|  | 10972 | case Builtin::BI__builtin_sadd_overflow: | 
|  | 10973 | case Builtin::BI__builtin_uadd_overflow: | 
|  | 10974 | case Builtin::BI__builtin_uaddl_overflow: | 
|  | 10975 | case Builtin::BI__builtin_uaddll_overflow: | 
|  | 10976 | case Builtin::BI__builtin_usub_overflow: | 
|  | 10977 | case Builtin::BI__builtin_usubl_overflow: | 
|  | 10978 | case Builtin::BI__builtin_usubll_overflow: | 
|  | 10979 | case Builtin::BI__builtin_umul_overflow: | 
|  | 10980 | case Builtin::BI__builtin_umull_overflow: | 
|  | 10981 | case Builtin::BI__builtin_umulll_overflow: | 
|  | 10982 | case Builtin::BI__builtin_saddl_overflow: | 
|  | 10983 | case Builtin::BI__builtin_saddll_overflow: | 
|  | 10984 | case Builtin::BI__builtin_ssub_overflow: | 
|  | 10985 | case Builtin::BI__builtin_ssubl_overflow: | 
|  | 10986 | case Builtin::BI__builtin_ssubll_overflow: | 
|  | 10987 | case Builtin::BI__builtin_smul_overflow: | 
|  | 10988 | case Builtin::BI__builtin_smull_overflow: | 
|  | 10989 | case Builtin::BI__builtin_smulll_overflow: { | 
|  | 10990 | LValue ResultLValue; | 
|  | 10991 | APSInt LHS, RHS; | 
|  | 10992 |  | 
|  | 10993 | QualType ResultType = E->getArg(2)->getType()->getPointeeType(); | 
|  | 10994 | if (!EvaluateInteger(E->getArg(0), LHS, Info) || | 
|  | 10995 | !EvaluateInteger(E->getArg(1), RHS, Info) || | 
|  | 10996 | !EvaluatePointer(E->getArg(2), ResultLValue, Info)) | 
|  | 10997 | return false; | 
|  | 10998 |  | 
|  | 10999 | APSInt Result; | 
|  | 11000 | bool DidOverflow = false; | 
|  | 11001 |  | 
|  | 11002 | // If the types don't have to match, enlarge all 3 to the largest of them. | 
|  | 11003 | if (BuiltinOp == Builtin::BI__builtin_add_overflow || | 
|  | 11004 | BuiltinOp == Builtin::BI__builtin_sub_overflow || | 
|  | 11005 | BuiltinOp == Builtin::BI__builtin_mul_overflow) { | 
|  | 11006 | bool IsSigned = LHS.isSigned() || RHS.isSigned() || | 
|  | 11007 | ResultType->isSignedIntegerOrEnumerationType(); | 
|  | 11008 | bool AllSigned = LHS.isSigned() && RHS.isSigned() && | 
|  | 11009 | ResultType->isSignedIntegerOrEnumerationType(); | 
|  | 11010 | uint64_t LHSSize = LHS.getBitWidth(); | 
|  | 11011 | uint64_t RHSSize = RHS.getBitWidth(); | 
|  | 11012 | uint64_t ResultSize = Info.Ctx.getTypeSize(ResultType); | 
|  | 11013 | uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize); | 
|  | 11014 |  | 
|  | 11015 | // Add an additional bit if the signedness isn't uniformly agreed to. We | 
|  | 11016 | // could do this ONLY if there is a signed and an unsigned that both have | 
|  | 11017 | // MaxBits, but the code to check that is pretty nasty.  The issue will be | 
|  | 11018 | // caught in the shrink-to-result later anyway. | 
|  | 11019 | if (IsSigned && !AllSigned) | 
|  | 11020 | ++MaxBits; | 
|  | 11021 |  | 
| Erich Keane | fc3dfd3 | 2019-05-30 21:35:32 +0000 | [diff] [blame] | 11022 | LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned); | 
|  | 11023 | RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned); | 
| Erich Keane | 0095827 | 2018-06-13 20:43:27 +0000 | [diff] [blame] | 11024 | Result = APSInt(MaxBits, !IsSigned); | 
|  | 11025 | } | 
|  | 11026 |  | 
|  | 11027 | // Find largest int. | 
|  | 11028 | switch (BuiltinOp) { | 
|  | 11029 | default: | 
|  | 11030 | llvm_unreachable("Invalid value for BuiltinOp"); | 
|  | 11031 | case Builtin::BI__builtin_add_overflow: | 
|  | 11032 | case Builtin::BI__builtin_sadd_overflow: | 
|  | 11033 | case Builtin::BI__builtin_saddl_overflow: | 
|  | 11034 | case Builtin::BI__builtin_saddll_overflow: | 
|  | 11035 | case Builtin::BI__builtin_uadd_overflow: | 
|  | 11036 | case Builtin::BI__builtin_uaddl_overflow: | 
|  | 11037 | case Builtin::BI__builtin_uaddll_overflow: | 
|  | 11038 | Result = LHS.isSigned() ? LHS.sadd_ov(RHS, DidOverflow) | 
|  | 11039 | : LHS.uadd_ov(RHS, DidOverflow); | 
|  | 11040 | break; | 
|  | 11041 | case Builtin::BI__builtin_sub_overflow: | 
|  | 11042 | case Builtin::BI__builtin_ssub_overflow: | 
|  | 11043 | case Builtin::BI__builtin_ssubl_overflow: | 
|  | 11044 | case Builtin::BI__builtin_ssubll_overflow: | 
|  | 11045 | case Builtin::BI__builtin_usub_overflow: | 
|  | 11046 | case Builtin::BI__builtin_usubl_overflow: | 
|  | 11047 | case Builtin::BI__builtin_usubll_overflow: | 
|  | 11048 | Result = LHS.isSigned() ? LHS.ssub_ov(RHS, DidOverflow) | 
|  | 11049 | : LHS.usub_ov(RHS, DidOverflow); | 
|  | 11050 | break; | 
|  | 11051 | case Builtin::BI__builtin_mul_overflow: | 
|  | 11052 | case Builtin::BI__builtin_smul_overflow: | 
|  | 11053 | case Builtin::BI__builtin_smull_overflow: | 
|  | 11054 | case Builtin::BI__builtin_smulll_overflow: | 
|  | 11055 | case Builtin::BI__builtin_umul_overflow: | 
|  | 11056 | case Builtin::BI__builtin_umull_overflow: | 
|  | 11057 | case Builtin::BI__builtin_umulll_overflow: | 
|  | 11058 | Result = LHS.isSigned() ? LHS.smul_ov(RHS, DidOverflow) | 
|  | 11059 | : LHS.umul_ov(RHS, DidOverflow); | 
|  | 11060 | break; | 
|  | 11061 | } | 
|  | 11062 |  | 
|  | 11063 | // In the case where multiple sizes are allowed, truncate and see if | 
|  | 11064 | // the values are the same. | 
|  | 11065 | if (BuiltinOp == Builtin::BI__builtin_add_overflow || | 
|  | 11066 | BuiltinOp == Builtin::BI__builtin_sub_overflow || | 
|  | 11067 | BuiltinOp == Builtin::BI__builtin_mul_overflow) { | 
|  | 11068 | // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead, | 
|  | 11069 | // since it will give us the behavior of a TruncOrSelf in the case where | 
|  | 11070 | // its parameter <= its size.  We previously set Result to be at least the | 
|  | 11071 | // type-size of the result, so getTypeSize(ResultType) <= Result.BitWidth | 
|  | 11072 | // will work exactly like TruncOrSelf. | 
|  | 11073 | APSInt Temp = Result.extOrTrunc(Info.Ctx.getTypeSize(ResultType)); | 
|  | 11074 | Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType()); | 
|  | 11075 |  | 
|  | 11076 | if (!APSInt::isSameValue(Temp, Result)) | 
|  | 11077 | DidOverflow = true; | 
|  | 11078 | Result = Temp; | 
|  | 11079 | } | 
|  | 11080 |  | 
|  | 11081 | APValue APV{Result}; | 
| Erich Keane | cb54964 | 2018-07-05 15:52:58 +0000 | [diff] [blame] | 11082 | if (!handleAssignment(Info, E, ResultLValue, ResultType, APV)) | 
|  | 11083 | return false; | 
| Erich Keane | 0095827 | 2018-06-13 20:43:27 +0000 | [diff] [blame] | 11084 | return Success(DidOverflow, E); | 
|  | 11085 | } | 
| Chris Lattner | 4deaa4e | 2008-10-06 05:28:25 +0000 | [diff] [blame] | 11086 | } | 
| Chris Lattner | 7174bf3 | 2008-07-12 00:38:25 +0000 | [diff] [blame] | 11087 | } | 
| Anders Carlsson | 4a3585b | 2008-07-08 15:34:11 +0000 | [diff] [blame] | 11088 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 11089 | /// Determine whether this is a pointer past the end of the complete | 
| Richard Smith | d20f1e6 | 2014-10-21 23:01:04 +0000 | [diff] [blame] | 11090 | /// object referred to by the lvalue. | 
|  | 11091 | static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx, | 
|  | 11092 | const LValue &LV) { | 
|  | 11093 | // A null pointer can be viewed as being "past the end" but we don't | 
|  | 11094 | // choose to look at it that way here. | 
|  | 11095 | if (!LV.getLValueBase()) | 
|  | 11096 | return false; | 
|  | 11097 |  | 
|  | 11098 | // If the designator is valid and refers to a subobject, we're not pointing | 
|  | 11099 | // past the end. | 
|  | 11100 | if (!LV.getLValueDesignator().Invalid && | 
|  | 11101 | !LV.getLValueDesignator().isOnePastTheEnd()) | 
|  | 11102 | return false; | 
|  | 11103 |  | 
| David Majnemer | c378ca5 | 2015-08-29 08:32:55 +0000 | [diff] [blame] | 11104 | // A pointer to an incomplete type might be past-the-end if the type's size is | 
|  | 11105 | // zero.  We cannot tell because the type is incomplete. | 
|  | 11106 | QualType Ty = getType(LV.getLValueBase()); | 
|  | 11107 | if (Ty->isIncompleteType()) | 
|  | 11108 | return true; | 
|  | 11109 |  | 
| Richard Smith | d20f1e6 | 2014-10-21 23:01:04 +0000 | [diff] [blame] | 11110 | // We're a past-the-end pointer if we point to the byte after the object, | 
|  | 11111 | // no matter what our type or path is. | 
| David Majnemer | c378ca5 | 2015-08-29 08:32:55 +0000 | [diff] [blame] | 11112 | auto Size = Ctx.getTypeSizeInChars(Ty); | 
| Richard Smith | d20f1e6 | 2014-10-21 23:01:04 +0000 | [diff] [blame] | 11113 | return LV.getLValueOffset() == Size; | 
|  | 11114 | } | 
|  | 11115 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11116 | namespace { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 11117 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 11118 | /// Data recursive integer evaluator of certain binary operators. | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11119 | /// | 
|  | 11120 | /// We use a data recursive algorithm for binary operators so that we are able | 
|  | 11121 | /// to handle extreme cases of chained binary operators without causing stack | 
|  | 11122 | /// overflow. | 
|  | 11123 | class DataRecursiveIntBinOpEvaluator { | 
|  | 11124 | struct EvalResult { | 
|  | 11125 | APValue Val; | 
|  | 11126 | bool Failed; | 
|  | 11127 |  | 
|  | 11128 | EvalResult() : Failed(false) { } | 
|  | 11129 |  | 
|  | 11130 | void swap(EvalResult &RHS) { | 
|  | 11131 | Val.swap(RHS.Val); | 
|  | 11132 | Failed = RHS.Failed; | 
|  | 11133 | RHS.Failed = false; | 
|  | 11134 | } | 
|  | 11135 | }; | 
|  | 11136 |  | 
|  | 11137 | struct Job { | 
|  | 11138 | const Expr *E; | 
|  | 11139 | EvalResult LHSResult; // meaningful only for binary operator expression. | 
|  | 11140 | enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 11141 |  | 
| David Blaikie | 7372606 | 2015-08-12 23:09:24 +0000 | [diff] [blame] | 11142 | Job() = default; | 
| Benjamin Kramer | 33e9760 | 2016-10-21 18:55:07 +0000 | [diff] [blame] | 11143 | Job(Job &&) = default; | 
| David Blaikie | 7372606 | 2015-08-12 23:09:24 +0000 | [diff] [blame] | 11144 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11145 | void startSpeculativeEval(EvalInfo &Info) { | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 11146 | SpecEvalRAII = SpeculativeEvaluationRAII(Info); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11147 | } | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 11148 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11149 | private: | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 11150 | SpeculativeEvaluationRAII SpecEvalRAII; | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11151 | }; | 
|  | 11152 |  | 
|  | 11153 | SmallVector<Job, 16> Queue; | 
|  | 11154 |  | 
|  | 11155 | IntExprEvaluator &IntEval; | 
|  | 11156 | EvalInfo &Info; | 
|  | 11157 | APValue &FinalResult; | 
|  | 11158 |  | 
|  | 11159 | public: | 
|  | 11160 | DataRecursiveIntBinOpEvaluator(IntExprEvaluator &IntEval, APValue &Result) | 
|  | 11161 | : IntEval(IntEval), Info(IntEval.getEvalInfo()), FinalResult(Result) { } | 
|  | 11162 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 11163 | /// True if \param E is a binary operator that we are going to handle | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11164 | /// data recursively. | 
|  | 11165 | /// We handle binary operators that are comma, logical, or that have operands | 
|  | 11166 | /// with integral or enumeration type. | 
|  | 11167 | static bool shouldEnqueue(const BinaryOperator *E) { | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11168 | return E->getOpcode() == BO_Comma || E->isLogicalOp() || | 
|  | 11169 | (E->isRValue() && E->getType()->isIntegralOrEnumerationType() && | 
| Richard Smith | 3a09d8b | 2016-06-04 00:22:31 +0000 | [diff] [blame] | 11170 | E->getLHS()->getType()->isIntegralOrEnumerationType() && | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11171 | E->getRHS()->getType()->isIntegralOrEnumerationType()); | 
| Eli Friedman | 5a332ea | 2008-11-13 06:09:17 +0000 | [diff] [blame] | 11172 | } | 
|  | 11173 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11174 | bool Traverse(const BinaryOperator *E) { | 
|  | 11175 | enqueue(E); | 
|  | 11176 | EvalResult PrevResult; | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11177 | while (!Queue.empty()) | 
|  | 11178 | process(PrevResult); | 
|  | 11179 |  | 
|  | 11180 | if (PrevResult.Failed) return false; | 
| Argyrios Kyrtzidis | 8d4677a | 2012-02-25 23:21:37 +0000 | [diff] [blame] | 11181 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11182 | FinalResult.swap(PrevResult.Val); | 
|  | 11183 | return true; | 
|  | 11184 | } | 
|  | 11185 |  | 
|  | 11186 | private: | 
|  | 11187 | bool Success(uint64_t Value, const Expr *E, APValue &Result) { | 
|  | 11188 | return IntEval.Success(Value, E, Result); | 
|  | 11189 | } | 
|  | 11190 | bool Success(const APSInt &Value, const Expr *E, APValue &Result) { | 
|  | 11191 | return IntEval.Success(Value, E, Result); | 
|  | 11192 | } | 
|  | 11193 | bool Error(const Expr *E) { | 
|  | 11194 | return IntEval.Error(E); | 
|  | 11195 | } | 
|  | 11196 | bool Error(const Expr *E, diag::kind D) { | 
|  | 11197 | return IntEval.Error(E, D); | 
|  | 11198 | } | 
|  | 11199 |  | 
|  | 11200 | OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { | 
|  | 11201 | return Info.CCEDiag(E, D); | 
|  | 11202 | } | 
|  | 11203 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 11204 | // Returns true if visiting the RHS is necessary, false otherwise. | 
| Argyrios Kyrtzidis | 5957b70 | 2012-03-22 02:13:06 +0000 | [diff] [blame] | 11205 | bool VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E, | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11206 | bool &SuppressRHSDiags); | 
|  | 11207 |  | 
|  | 11208 | bool VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, | 
|  | 11209 | const BinaryOperator *E, APValue &Result); | 
|  | 11210 |  | 
|  | 11211 | void EvaluateExpr(const Expr *E, EvalResult &Result) { | 
|  | 11212 | Result.Failed = !Evaluate(Result.Val, Info, E); | 
|  | 11213 | if (Result.Failed) | 
|  | 11214 | Result.Val = APValue(); | 
|  | 11215 | } | 
|  | 11216 |  | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11217 | void process(EvalResult &Result); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11218 |  | 
|  | 11219 | void enqueue(const Expr *E) { | 
|  | 11220 | E = E->IgnoreParens(); | 
|  | 11221 | Queue.resize(Queue.size()+1); | 
|  | 11222 | Queue.back().E = E; | 
|  | 11223 | Queue.back().Kind = Job::AnyExprKind; | 
|  | 11224 | } | 
|  | 11225 | }; | 
|  | 11226 |  | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 11227 | } | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11228 |  | 
|  | 11229 | bool DataRecursiveIntBinOpEvaluator:: | 
| Argyrios Kyrtzidis | 5957b70 | 2012-03-22 02:13:06 +0000 | [diff] [blame] | 11230 | VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E, | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11231 | bool &SuppressRHSDiags) { | 
|  | 11232 | if (E->getOpcode() == BO_Comma) { | 
|  | 11233 | // Ignore LHS but note if we could not evaluate it. | 
|  | 11234 | if (LHSResult.Failed) | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11235 | return Info.noteSideEffect(); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11236 | return true; | 
|  | 11237 | } | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11238 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11239 | if (E->isLogicalOp()) { | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11240 | bool LHSAsBool; | 
|  | 11241 | if (!LHSResult.Failed && HandleConversionToBool(LHSResult.Val, LHSAsBool)) { | 
| Argyrios Kyrtzidis | 8d4677a | 2012-02-25 23:21:37 +0000 | [diff] [blame] | 11242 | // We were able to evaluate the LHS, see if we can get away with not | 
|  | 11243 | // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11244 | if (LHSAsBool == (E->getOpcode() == BO_LOr)) { | 
|  | 11245 | Success(LHSAsBool, E, LHSResult.Val); | 
| Argyrios Kyrtzidis | 5957b70 | 2012-03-22 02:13:06 +0000 | [diff] [blame] | 11246 | return false; // Ignore RHS | 
| Argyrios Kyrtzidis | 8d4677a | 2012-02-25 23:21:37 +0000 | [diff] [blame] | 11247 | } | 
|  | 11248 | } else { | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11249 | LHSResult.Failed = true; | 
|  | 11250 |  | 
| Argyrios Kyrtzidis | 8d4677a | 2012-02-25 23:21:37 +0000 | [diff] [blame] | 11251 | // Since we weren't able to evaluate the left hand side, it | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 11252 | // might have had side effects. | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11253 | if (!Info.noteSideEffect()) | 
|  | 11254 | return false; | 
|  | 11255 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11256 | // We can't evaluate the LHS; however, sometimes the result | 
|  | 11257 | // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. | 
|  | 11258 | // Don't ignore RHS and suppress diagnostics from this arm. | 
|  | 11259 | SuppressRHSDiags = true; | 
|  | 11260 | } | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11261 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11262 | return true; | 
|  | 11263 | } | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11264 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11265 | assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && | 
|  | 11266 | E->getRHS()->getType()->isIntegralOrEnumerationType()); | 
| Richard Smith | 4e66f1f | 2013-11-06 02:19:10 +0000 | [diff] [blame] | 11267 |  | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 11268 | if (LHSResult.Failed && !Info.noteFailure()) | 
| Argyrios Kyrtzidis | 5957b70 | 2012-03-22 02:13:06 +0000 | [diff] [blame] | 11269 | return false; // Ignore RHS; | 
|  | 11270 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11271 | return true; | 
|  | 11272 | } | 
| Argyrios Kyrtzidis | 8d4677a | 2012-02-25 23:21:37 +0000 | [diff] [blame] | 11273 |  | 
| Benjamin Kramer | f6021ec | 2017-03-21 21:35:04 +0000 | [diff] [blame] | 11274 | static void addOrSubLValueAsInteger(APValue &LVal, const APSInt &Index, | 
|  | 11275 | bool IsSub) { | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 11276 | // Compute the new offset in the appropriate width, wrapping at 64 bits. | 
|  | 11277 | // FIXME: When compiling for a 32-bit target, we should use 32-bit | 
|  | 11278 | // offsets. | 
|  | 11279 | assert(!LVal.hasLValuePath() && "have designator for integer lvalue"); | 
|  | 11280 | CharUnits &Offset = LVal.getLValueOffset(); | 
|  | 11281 | uint64_t Offset64 = Offset.getQuantity(); | 
|  | 11282 | uint64_t Index64 = Index.extOrTrunc(64).getZExtValue(); | 
|  | 11283 | Offset = CharUnits::fromQuantity(IsSub ? Offset64 - Index64 | 
|  | 11284 | : Offset64 + Index64); | 
|  | 11285 | } | 
|  | 11286 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11287 | bool DataRecursiveIntBinOpEvaluator:: | 
|  | 11288 | VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, | 
|  | 11289 | const BinaryOperator *E, APValue &Result) { | 
|  | 11290 | if (E->getOpcode() == BO_Comma) { | 
|  | 11291 | if (RHSResult.Failed) | 
|  | 11292 | return false; | 
|  | 11293 | Result = RHSResult.Val; | 
|  | 11294 | return true; | 
|  | 11295 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11296 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11297 | if (E->isLogicalOp()) { | 
|  | 11298 | bool lhsResult, rhsResult; | 
|  | 11299 | bool LHSIsOK = HandleConversionToBool(LHSResult.Val, lhsResult); | 
|  | 11300 | bool RHSIsOK = HandleConversionToBool(RHSResult.Val, rhsResult); | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11301 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11302 | if (LHSIsOK) { | 
|  | 11303 | if (RHSIsOK) { | 
|  | 11304 | if (E->getOpcode() == BO_LOr) | 
|  | 11305 | return Success(lhsResult || rhsResult, E, Result); | 
|  | 11306 | else | 
|  | 11307 | return Success(lhsResult && rhsResult, E, Result); | 
|  | 11308 | } | 
|  | 11309 | } else { | 
|  | 11310 | if (RHSIsOK) { | 
| Argyrios Kyrtzidis | 8d4677a | 2012-02-25 23:21:37 +0000 | [diff] [blame] | 11311 | // We can't evaluate the LHS; however, sometimes the result | 
|  | 11312 | // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. | 
|  | 11313 | if (rhsResult == (E->getOpcode() == BO_LOr)) | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11314 | return Success(rhsResult, E, Result); | 
| Argyrios Kyrtzidis | 8d4677a | 2012-02-25 23:21:37 +0000 | [diff] [blame] | 11315 | } | 
|  | 11316 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11317 |  | 
| Argyrios Kyrtzidis | 8d4677a | 2012-02-25 23:21:37 +0000 | [diff] [blame] | 11318 | return false; | 
|  | 11319 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11320 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11321 | assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && | 
|  | 11322 | E->getRHS()->getType()->isIntegralOrEnumerationType()); | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11323 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11324 | if (LHSResult.Failed || RHSResult.Failed) | 
|  | 11325 | return false; | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11326 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11327 | const APValue &LHSVal = LHSResult.Val; | 
|  | 11328 | const APValue &RHSVal = RHSResult.Val; | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11329 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11330 | // Handle cases like (unsigned long)&a + 4. | 
|  | 11331 | if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) { | 
|  | 11332 | Result = LHSVal; | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 11333 | addOrSubLValueAsInteger(Result, RHSVal.getInt(), E->getOpcode() == BO_Sub); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11334 | return true; | 
|  | 11335 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11336 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11337 | // Handle cases like 4 + (unsigned long)&a | 
|  | 11338 | if (E->getOpcode() == BO_Add && | 
|  | 11339 | RHSVal.isLValue() && LHSVal.isInt()) { | 
|  | 11340 | Result = RHSVal; | 
| Richard Smith | d6cc198 | 2017-01-31 02:23:02 +0000 | [diff] [blame] | 11341 | addOrSubLValueAsInteger(Result, LHSVal.getInt(), /*IsSub*/false); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11342 | return true; | 
|  | 11343 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11344 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11345 | if (E->getOpcode() == BO_Sub && LHSVal.isLValue() && RHSVal.isLValue()) { | 
|  | 11346 | // Handle (intptr_t)&&A - (intptr_t)&&B. | 
|  | 11347 | if (!LHSVal.getLValueOffset().isZero() || | 
|  | 11348 | !RHSVal.getLValueOffset().isZero()) | 
|  | 11349 | return false; | 
|  | 11350 | const Expr *LHSExpr = LHSVal.getLValueBase().dyn_cast<const Expr*>(); | 
|  | 11351 | const Expr *RHSExpr = RHSVal.getLValueBase().dyn_cast<const Expr*>(); | 
|  | 11352 | if (!LHSExpr || !RHSExpr) | 
|  | 11353 | return false; | 
|  | 11354 | const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr); | 
|  | 11355 | const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr); | 
|  | 11356 | if (!LHSAddrExpr || !RHSAddrExpr) | 
|  | 11357 | return false; | 
|  | 11358 | // Make sure both labels come from the same function. | 
|  | 11359 | if (LHSAddrExpr->getLabel()->getDeclContext() != | 
|  | 11360 | RHSAddrExpr->getLabel()->getDeclContext()) | 
|  | 11361 | return false; | 
|  | 11362 | Result = APValue(LHSAddrExpr, RHSAddrExpr); | 
|  | 11363 | return true; | 
|  | 11364 | } | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 11365 |  | 
|  | 11366 | // All the remaining cases expect both operands to be an integer | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11367 | if (!LHSVal.isInt() || !RHSVal.isInt()) | 
|  | 11368 | return Error(E); | 
| Richard Smith | 43e7773 | 2013-05-07 04:50:00 +0000 | [diff] [blame] | 11369 |  | 
|  | 11370 | // Set up the width and signedness manually, in case it can't be deduced | 
|  | 11371 | // from the operation we're performing. | 
|  | 11372 | // FIXME: Don't do this in the cases where we can deduce it. | 
|  | 11373 | APSInt Value(Info.Ctx.getIntWidth(E->getType()), | 
|  | 11374 | E->getType()->isUnsignedIntegerOrEnumerationType()); | 
|  | 11375 | if (!handleIntIntBinOp(Info, E, LHSVal.getInt(), E->getOpcode(), | 
|  | 11376 | RHSVal.getInt(), Value)) | 
|  | 11377 | return false; | 
|  | 11378 | return Success(Value, E, Result); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11379 | } | 
|  | 11380 |  | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11381 | void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11382 | Job &job = Queue.back(); | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11383 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11384 | switch (job.Kind) { | 
|  | 11385 | case Job::AnyExprKind: { | 
|  | 11386 | if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(job.E)) { | 
|  | 11387 | if (shouldEnqueue(Bop)) { | 
|  | 11388 | job.Kind = Job::BinOpKind; | 
|  | 11389 | enqueue(Bop->getLHS()); | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11390 | return; | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11391 | } | 
|  | 11392 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11393 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11394 | EvaluateExpr(job.E, Result); | 
|  | 11395 | Queue.pop_back(); | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11396 | return; | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11397 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11398 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11399 | case Job::BinOpKind: { | 
|  | 11400 | const BinaryOperator *Bop = cast<BinaryOperator>(job.E); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11401 | bool SuppressRHSDiags = false; | 
| Argyrios Kyrtzidis | 5957b70 | 2012-03-22 02:13:06 +0000 | [diff] [blame] | 11402 | if (!VisitBinOpLHSOnly(Result, Bop, SuppressRHSDiags)) { | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11403 | Queue.pop_back(); | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11404 | return; | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11405 | } | 
|  | 11406 | if (SuppressRHSDiags) | 
|  | 11407 | job.startSpeculativeEval(Info); | 
| Argyrios Kyrtzidis | 5957b70 | 2012-03-22 02:13:06 +0000 | [diff] [blame] | 11408 | job.LHSResult.swap(Result); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11409 | job.Kind = Job::BinOpVisitedLHSKind; | 
|  | 11410 | enqueue(Bop->getRHS()); | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11411 | return; | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11412 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11413 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11414 | case Job::BinOpVisitedLHSKind: { | 
|  | 11415 | const BinaryOperator *Bop = cast<BinaryOperator>(job.E); | 
|  | 11416 | EvalResult RHS; | 
|  | 11417 | RHS.swap(Result); | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11418 | Result.Failed = !VisitBinOp(job.LHSResult, RHS, Bop, Result.Val); | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11419 | Queue.pop_back(); | 
| Richard Trieu | ba4d087 | 2012-03-21 23:30:30 +0000 | [diff] [blame] | 11420 | return; | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11421 | } | 
|  | 11422 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 11423 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11424 | llvm_unreachable("Invalid Job::Kind!"); | 
|  | 11425 | } | 
|  | 11426 |  | 
| George Burgess IV | 8c892b5 | 2016-05-25 22:31:54 +0000 | [diff] [blame] | 11427 | namespace { | 
|  | 11428 | /// Used when we determine that we should fail, but can keep evaluating prior to | 
|  | 11429 | /// noting that we had a failure. | 
|  | 11430 | class DelayedNoteFailureRAII { | 
|  | 11431 | EvalInfo &Info; | 
|  | 11432 | bool NoteFailure; | 
|  | 11433 |  | 
|  | 11434 | public: | 
|  | 11435 | DelayedNoteFailureRAII(EvalInfo &Info, bool NoteFailure = true) | 
|  | 11436 | : Info(Info), NoteFailure(NoteFailure) {} | 
|  | 11437 | ~DelayedNoteFailureRAII() { | 
|  | 11438 | if (NoteFailure) { | 
|  | 11439 | bool ContinueAfterFailure = Info.noteFailure(); | 
|  | 11440 | (void)ContinueAfterFailure; | 
|  | 11441 | assert(ContinueAfterFailure && | 
|  | 11442 | "Shouldn't have kept evaluating on failure."); | 
|  | 11443 | } | 
|  | 11444 | } | 
|  | 11445 | }; | 
|  | 11446 | } | 
|  | 11447 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11448 | template <class SuccessCB, class AfterCB> | 
|  | 11449 | static bool | 
|  | 11450 | EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, | 
|  | 11451 | SuccessCB &&Success, AfterCB &&DoAfter) { | 
|  | 11452 | assert(E->isComparisonOp() && "expected comparison operator"); | 
|  | 11453 | assert((E->getOpcode() == BO_Cmp || | 
|  | 11454 | E->getType()->isIntegralOrEnumerationType()) && | 
|  | 11455 | "unsupported binary expression evaluation"); | 
|  | 11456 | auto Error = [&](const Expr *E) { | 
|  | 11457 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
|  | 11458 | return false; | 
|  | 11459 | }; | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11460 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11461 | using CCR = ComparisonCategoryResult; | 
|  | 11462 | bool IsRelational = E->isRelationalOp(); | 
|  | 11463 | bool IsEquality = E->isEqualityOp(); | 
|  | 11464 | if (E->getOpcode() == BO_Cmp) { | 
|  | 11465 | const ComparisonCategoryInfo &CmpInfo = | 
|  | 11466 | Info.Ctx.CompCategories.getInfoForType(E->getType()); | 
|  | 11467 | IsRelational = CmpInfo.isOrdered(); | 
|  | 11468 | IsEquality = CmpInfo.isEquality(); | 
|  | 11469 | } | 
| Eli Friedman | 5a332ea | 2008-11-13 06:09:17 +0000 | [diff] [blame] | 11470 |  | 
| Anders Carlsson | acc7981 | 2008-11-16 07:17:21 +0000 | [diff] [blame] | 11471 | QualType LHSTy = E->getLHS()->getType(); | 
|  | 11472 | QualType RHSTy = E->getRHS()->getType(); | 
| Daniel Dunbar | 74f2425b | 2009-01-29 06:43:41 +0000 | [diff] [blame] | 11473 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11474 | if (LHSTy->isIntegralOrEnumerationType() && | 
|  | 11475 | RHSTy->isIntegralOrEnumerationType()) { | 
|  | 11476 | APSInt LHS, RHS; | 
|  | 11477 | bool LHSOK = EvaluateInteger(E->getLHS(), LHS, Info); | 
|  | 11478 | if (!LHSOK && !Info.noteFailure()) | 
|  | 11479 | return false; | 
|  | 11480 | if (!EvaluateInteger(E->getRHS(), RHS, Info) || !LHSOK) | 
|  | 11481 | return false; | 
|  | 11482 | if (LHS < RHS) | 
|  | 11483 | return Success(CCR::Less, E); | 
|  | 11484 | if (LHS > RHS) | 
|  | 11485 | return Success(CCR::Greater, E); | 
|  | 11486 | return Success(CCR::Equal, E); | 
|  | 11487 | } | 
|  | 11488 |  | 
| Leonard Chan | ce1d4f1 | 2019-02-21 20:50:09 +0000 | [diff] [blame] | 11489 | if (LHSTy->isFixedPointType() || RHSTy->isFixedPointType()) { | 
|  | 11490 | APFixedPoint LHSFX(Info.Ctx.getFixedPointSemantics(LHSTy)); | 
|  | 11491 | APFixedPoint RHSFX(Info.Ctx.getFixedPointSemantics(RHSTy)); | 
|  | 11492 |  | 
|  | 11493 | bool LHSOK = EvaluateFixedPointOrInteger(E->getLHS(), LHSFX, Info); | 
|  | 11494 | if (!LHSOK && !Info.noteFailure()) | 
|  | 11495 | return false; | 
|  | 11496 | if (!EvaluateFixedPointOrInteger(E->getRHS(), RHSFX, Info) || !LHSOK) | 
|  | 11497 | return false; | 
|  | 11498 | if (LHSFX < RHSFX) | 
|  | 11499 | return Success(CCR::Less, E); | 
|  | 11500 | if (LHSFX > RHSFX) | 
|  | 11501 | return Success(CCR::Greater, E); | 
|  | 11502 | return Success(CCR::Equal, E); | 
|  | 11503 | } | 
|  | 11504 |  | 
| Chandler Carruth | b29a743 | 2014-10-11 11:03:30 +0000 | [diff] [blame] | 11505 | if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) { | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 11506 | ComplexValue LHS, RHS; | 
| Chandler Carruth | b29a743 | 2014-10-11 11:03:30 +0000 | [diff] [blame] | 11507 | bool LHSOK; | 
| Josh Magee | 4d1a79b | 2015-02-04 21:50:20 +0000 | [diff] [blame] | 11508 | if (E->isAssignmentOp()) { | 
|  | 11509 | LValue LV; | 
|  | 11510 | EvaluateLValue(E->getLHS(), LV, Info); | 
|  | 11511 | LHSOK = false; | 
|  | 11512 | } else if (LHSTy->isRealFloatingType()) { | 
| Chandler Carruth | b29a743 | 2014-10-11 11:03:30 +0000 | [diff] [blame] | 11513 | LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info); | 
|  | 11514 | if (LHSOK) { | 
|  | 11515 | LHS.makeComplexFloat(); | 
|  | 11516 | LHS.FloatImag = APFloat(LHS.FloatReal.getSemantics()); | 
|  | 11517 | } | 
|  | 11518 | } else { | 
|  | 11519 | LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); | 
|  | 11520 | } | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 11521 | if (!LHSOK && !Info.noteFailure()) | 
| Daniel Dunbar | 74f2425b | 2009-01-29 06:43:41 +0000 | [diff] [blame] | 11522 | return false; | 
|  | 11523 |  | 
| Chandler Carruth | b29a743 | 2014-10-11 11:03:30 +0000 | [diff] [blame] | 11524 | if (E->getRHS()->getType()->isRealFloatingType()) { | 
|  | 11525 | if (!EvaluateFloat(E->getRHS(), RHS.FloatReal, Info) || !LHSOK) | 
|  | 11526 | return false; | 
|  | 11527 | RHS.makeComplexFloat(); | 
|  | 11528 | RHS.FloatImag = APFloat(RHS.FloatReal.getSemantics()); | 
|  | 11529 | } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) | 
| Daniel Dunbar | 74f2425b | 2009-01-29 06:43:41 +0000 | [diff] [blame] | 11530 | return false; | 
|  | 11531 |  | 
|  | 11532 | if (LHS.isComplexFloat()) { | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 11533 | APFloat::cmpResult CR_r = | 
| Daniel Dunbar | 74f2425b | 2009-01-29 06:43:41 +0000 | [diff] [blame] | 11534 | LHS.getComplexFloatReal().compare(RHS.getComplexFloatReal()); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 11535 | APFloat::cmpResult CR_i = | 
| Daniel Dunbar | 74f2425b | 2009-01-29 06:43:41 +0000 | [diff] [blame] | 11536 | LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag()); | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11537 | bool IsEqual = CR_r == APFloat::cmpEqual && CR_i == APFloat::cmpEqual; | 
|  | 11538 | return Success(IsEqual ? CCR::Equal : CCR::Nonequal, E); | 
| Daniel Dunbar | 74f2425b | 2009-01-29 06:43:41 +0000 | [diff] [blame] | 11539 | } else { | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11540 | assert(IsEquality && "invalid complex comparison"); | 
|  | 11541 | bool IsEqual = LHS.getComplexIntReal() == RHS.getComplexIntReal() && | 
|  | 11542 | LHS.getComplexIntImag() == RHS.getComplexIntImag(); | 
|  | 11543 | return Success(IsEqual ? CCR::Equal : CCR::Nonequal, E); | 
| Daniel Dunbar | 74f2425b | 2009-01-29 06:43:41 +0000 | [diff] [blame] | 11544 | } | 
|  | 11545 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 11546 |  | 
| Anders Carlsson | acc7981 | 2008-11-16 07:17:21 +0000 | [diff] [blame] | 11547 | if (LHSTy->isRealFloatingType() && | 
|  | 11548 | RHSTy->isRealFloatingType()) { | 
|  | 11549 | APFloat RHS(0.0), LHS(0.0); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 11550 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 11551 | bool LHSOK = EvaluateFloat(E->getRHS(), RHS, Info); | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 11552 | if (!LHSOK && !Info.noteFailure()) | 
| Anders Carlsson | acc7981 | 2008-11-16 07:17:21 +0000 | [diff] [blame] | 11553 | return false; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 11554 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 11555 | if (!EvaluateFloat(E->getLHS(), LHS, Info) || !LHSOK) | 
| Anders Carlsson | acc7981 | 2008-11-16 07:17:21 +0000 | [diff] [blame] | 11556 | return false; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 11557 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11558 | assert(E->isComparisonOp() && "Invalid binary operator!"); | 
|  | 11559 | auto GetCmpRes = [&]() { | 
|  | 11560 | switch (LHS.compare(RHS)) { | 
|  | 11561 | case APFloat::cmpEqual: | 
|  | 11562 | return CCR::Equal; | 
|  | 11563 | case APFloat::cmpLessThan: | 
|  | 11564 | return CCR::Less; | 
|  | 11565 | case APFloat::cmpGreaterThan: | 
|  | 11566 | return CCR::Greater; | 
|  | 11567 | case APFloat::cmpUnordered: | 
|  | 11568 | return CCR::Unordered; | 
|  | 11569 | } | 
| Simon Pilgrim | 3366dcf | 2018-05-08 09:40:32 +0000 | [diff] [blame] | 11570 | llvm_unreachable("Unrecognised APFloat::cmpResult enum"); | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11571 | }; | 
|  | 11572 | return Success(GetCmpRes(), E); | 
| Anders Carlsson | acc7981 | 2008-11-16 07:17:21 +0000 | [diff] [blame] | 11573 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 11574 |  | 
| Eli Friedman | a38da57 | 2009-04-28 19:17:36 +0000 | [diff] [blame] | 11575 | if (LHSTy->isPointerType() && RHSTy->isPointerType()) { | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11576 | LValue LHSValue, RHSValue; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 11577 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11578 | bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info); | 
|  | 11579 | if (!LHSOK && !Info.noteFailure()) | 
|  | 11580 | return false; | 
| Eli Friedman | 6400433 | 2009-03-23 04:38:34 +0000 | [diff] [blame] | 11581 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11582 | if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) | 
|  | 11583 | return false; | 
| Eli Friedman | 6400433 | 2009-03-23 04:38:34 +0000 | [diff] [blame] | 11584 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11585 | // Reject differing bases from the normal codepath; we special-case | 
|  | 11586 | // comparisons to null. | 
|  | 11587 | if (!HasSameBase(LHSValue, RHSValue)) { | 
|  | 11588 | // Inequalities and subtractions between unrelated pointers have | 
|  | 11589 | // unspecified or undefined behavior. | 
|  | 11590 | if (!IsEquality) | 
|  | 11591 | return Error(E); | 
|  | 11592 | // A constant address may compare equal to the address of a symbol. | 
|  | 11593 | // The one exception is that address of an object cannot compare equal | 
|  | 11594 | // to a null pointer constant. | 
|  | 11595 | if ((!LHSValue.Base && !LHSValue.Offset.isZero()) || | 
|  | 11596 | (!RHSValue.Base && !RHSValue.Offset.isZero())) | 
|  | 11597 | return Error(E); | 
|  | 11598 | // It's implementation-defined whether distinct literals will have | 
|  | 11599 | // distinct addresses. In clang, the result of such a comparison is | 
|  | 11600 | // unspecified, so it is not a constant expression. However, we do know | 
|  | 11601 | // that the address of a literal will be non-null. | 
|  | 11602 | if ((IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue)) && | 
|  | 11603 | LHSValue.Base && RHSValue.Base) | 
|  | 11604 | return Error(E); | 
|  | 11605 | // We can't tell whether weak symbols will end up pointing to the same | 
|  | 11606 | // object. | 
|  | 11607 | if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue)) | 
|  | 11608 | return Error(E); | 
|  | 11609 | // We can't compare the address of the start of one object with the | 
|  | 11610 | // past-the-end address of another object, per C++ DR1652. | 
|  | 11611 | if ((LHSValue.Base && LHSValue.Offset.isZero() && | 
|  | 11612 | isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) || | 
|  | 11613 | (RHSValue.Base && RHSValue.Offset.isZero() && | 
|  | 11614 | isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue))) | 
|  | 11615 | return Error(E); | 
|  | 11616 | // We can't tell whether an object is at the same address as another | 
|  | 11617 | // zero sized object. | 
|  | 11618 | if ((RHSValue.Base && isZeroSized(LHSValue)) || | 
|  | 11619 | (LHSValue.Base && isZeroSized(RHSValue))) | 
|  | 11620 | return Error(E); | 
|  | 11621 | return Success(CCR::Nonequal, E); | 
|  | 11622 | } | 
| Eli Friedman | 6400433 | 2009-03-23 04:38:34 +0000 | [diff] [blame] | 11623 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11624 | const CharUnits &LHSOffset = LHSValue.getLValueOffset(); | 
|  | 11625 | const CharUnits &RHSOffset = RHSValue.getLValueOffset(); | 
| Richard Smith | 1b47041 | 2012-02-01 08:10:20 +0000 | [diff] [blame] | 11626 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11627 | SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator(); | 
|  | 11628 | SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator(); | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 11629 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11630 | // C++11 [expr.rel]p3: | 
|  | 11631 | //   Pointers to void (after pointer conversions) can be compared, with a | 
|  | 11632 | //   result defined as follows: If both pointers represent the same | 
|  | 11633 | //   address or are both the null pointer value, the result is true if the | 
|  | 11634 | //   operator is <= or >= and false otherwise; otherwise the result is | 
|  | 11635 | //   unspecified. | 
|  | 11636 | // We interpret this as applying to pointers to *cv* void. | 
|  | 11637 | if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && IsRelational) | 
|  | 11638 | Info.CCEDiag(E, diag::note_constexpr_void_comparison); | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 11639 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11640 | // C++11 [expr.rel]p2: | 
|  | 11641 | // - If two pointers point to non-static data members of the same object, | 
|  | 11642 | //   or to subobjects or array elements fo such members, recursively, the | 
|  | 11643 | //   pointer to the later declared member compares greater provided the | 
|  | 11644 | //   two members have the same access control and provided their class is | 
|  | 11645 | //   not a union. | 
|  | 11646 | //   [...] | 
|  | 11647 | // - Otherwise pointer comparisons are unspecified. | 
|  | 11648 | if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) { | 
|  | 11649 | bool WasArrayIndex; | 
|  | 11650 | unsigned Mismatch = FindDesignatorMismatch( | 
|  | 11651 | getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex); | 
|  | 11652 | // At the point where the designators diverge, the comparison has a | 
|  | 11653 | // specified value if: | 
|  | 11654 | //  - we are comparing array indices | 
|  | 11655 | //  - we are comparing fields of a union, or fields with the same access | 
|  | 11656 | // Otherwise, the result is unspecified and thus the comparison is not a | 
|  | 11657 | // constant expression. | 
|  | 11658 | if (!WasArrayIndex && Mismatch < LHSDesignator.Entries.size() && | 
|  | 11659 | Mismatch < RHSDesignator.Entries.size()) { | 
|  | 11660 | const FieldDecl *LF = getAsField(LHSDesignator.Entries[Mismatch]); | 
|  | 11661 | const FieldDecl *RF = getAsField(RHSDesignator.Entries[Mismatch]); | 
|  | 11662 | if (!LF && !RF) | 
|  | 11663 | Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_classes); | 
|  | 11664 | else if (!LF) | 
|  | 11665 | Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field) | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 11666 | << getAsBaseClass(LHSDesignator.Entries[Mismatch]) | 
|  | 11667 | << RF->getParent() << RF; | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11668 | else if (!RF) | 
|  | 11669 | Info.CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field) | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 11670 | << getAsBaseClass(RHSDesignator.Entries[Mismatch]) | 
|  | 11671 | << LF->getParent() << LF; | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11672 | else if (!LF->getParent()->isUnion() && | 
|  | 11673 | LF->getAccess() != RF->getAccess()) | 
|  | 11674 | Info.CCEDiag(E, | 
|  | 11675 | diag::note_constexpr_pointer_comparison_differing_access) | 
| Richard Smith | 84f6dcf | 2012-02-02 01:16:57 +0000 | [diff] [blame] | 11676 | << LF << LF->getAccess() << RF << RF->getAccess() | 
|  | 11677 | << LF->getParent(); | 
| Eli Friedman | a38da57 | 2009-04-28 19:17:36 +0000 | [diff] [blame] | 11678 | } | 
| Anders Carlsson | 9f9e424 | 2008-11-16 19:01:22 +0000 | [diff] [blame] | 11679 | } | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11680 |  | 
|  | 11681 | // The comparison here must be unsigned, and performed with the same | 
|  | 11682 | // width as the pointer. | 
|  | 11683 | unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy); | 
|  | 11684 | uint64_t CompareLHS = LHSOffset.getQuantity(); | 
|  | 11685 | uint64_t CompareRHS = RHSOffset.getQuantity(); | 
|  | 11686 | assert(PtrSize <= 64 && "Unexpected pointer width"); | 
|  | 11687 | uint64_t Mask = ~0ULL >> (64 - PtrSize); | 
|  | 11688 | CompareLHS &= Mask; | 
|  | 11689 | CompareRHS &= Mask; | 
|  | 11690 |  | 
|  | 11691 | // If there is a base and this is a relational operator, we can only | 
|  | 11692 | // compare pointers within the object in question; otherwise, the result | 
|  | 11693 | // depends on where the object is located in memory. | 
|  | 11694 | if (!LHSValue.Base.isNull() && IsRelational) { | 
|  | 11695 | QualType BaseTy = getType(LHSValue.Base); | 
|  | 11696 | if (BaseTy->isIncompleteType()) | 
|  | 11697 | return Error(E); | 
|  | 11698 | CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); | 
|  | 11699 | uint64_t OffsetLimit = Size.getQuantity(); | 
|  | 11700 | if (CompareLHS > OffsetLimit || CompareRHS > OffsetLimit) | 
|  | 11701 | return Error(E); | 
|  | 11702 | } | 
|  | 11703 |  | 
|  | 11704 | if (CompareLHS < CompareRHS) | 
|  | 11705 | return Success(CCR::Less, E); | 
|  | 11706 | if (CompareLHS > CompareRHS) | 
|  | 11707 | return Success(CCR::Greater, E); | 
|  | 11708 | return Success(CCR::Equal, E); | 
| Anders Carlsson | 9f9e424 | 2008-11-16 19:01:22 +0000 | [diff] [blame] | 11709 | } | 
| Richard Smith | 7bb0067 | 2012-02-01 01:42:44 +0000 | [diff] [blame] | 11710 |  | 
|  | 11711 | if (LHSTy->isMemberPointerType()) { | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11712 | assert(IsEquality && "unexpected member pointer operation"); | 
| Richard Smith | 7bb0067 | 2012-02-01 01:42:44 +0000 | [diff] [blame] | 11713 | assert(RHSTy->isMemberPointerType() && "invalid comparison"); | 
|  | 11714 |  | 
|  | 11715 | MemberPtr LHSValue, RHSValue; | 
|  | 11716 |  | 
|  | 11717 | bool LHSOK = EvaluateMemberPointer(E->getLHS(), LHSValue, Info); | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 11718 | if (!LHSOK && !Info.noteFailure()) | 
| Richard Smith | 7bb0067 | 2012-02-01 01:42:44 +0000 | [diff] [blame] | 11719 | return false; | 
|  | 11720 |  | 
|  | 11721 | if (!EvaluateMemberPointer(E->getRHS(), RHSValue, Info) || !LHSOK) | 
|  | 11722 | return false; | 
|  | 11723 |  | 
|  | 11724 | // C++11 [expr.eq]p2: | 
|  | 11725 | //   If both operands are null, they compare equal. Otherwise if only one is | 
|  | 11726 | //   null, they compare unequal. | 
|  | 11727 | if (!LHSValue.getDecl() || !RHSValue.getDecl()) { | 
|  | 11728 | bool Equal = !LHSValue.getDecl() && !RHSValue.getDecl(); | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11729 | return Success(Equal ? CCR::Equal : CCR::Nonequal, E); | 
| Richard Smith | 7bb0067 | 2012-02-01 01:42:44 +0000 | [diff] [blame] | 11730 | } | 
|  | 11731 |  | 
|  | 11732 | //   Otherwise if either is a pointer to a virtual member function, the | 
|  | 11733 | //   result is unspecified. | 
|  | 11734 | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LHSValue.getDecl())) | 
|  | 11735 | if (MD->isVirtual()) | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11736 | Info.CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD; | 
| Richard Smith | 7bb0067 | 2012-02-01 01:42:44 +0000 | [diff] [blame] | 11737 | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(RHSValue.getDecl())) | 
|  | 11738 | if (MD->isVirtual()) | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11739 | Info.CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD; | 
| Richard Smith | 7bb0067 | 2012-02-01 01:42:44 +0000 | [diff] [blame] | 11740 |  | 
|  | 11741 | //   Otherwise they compare equal if and only if they would refer to the | 
|  | 11742 | //   same member of the same most derived object or the same subobject if | 
|  | 11743 | //   they were dereferenced with a hypothetical object of the associated | 
|  | 11744 | //   class type. | 
|  | 11745 | bool Equal = LHSValue == RHSValue; | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11746 | return Success(Equal ? CCR::Equal : CCR::Nonequal, E); | 
| Richard Smith | 7bb0067 | 2012-02-01 01:42:44 +0000 | [diff] [blame] | 11747 | } | 
|  | 11748 |  | 
| Richard Smith | ab44d9b | 2012-02-14 22:35:28 +0000 | [diff] [blame] | 11749 | if (LHSTy->isNullPtrType()) { | 
|  | 11750 | assert(E->isComparisonOp() && "unexpected nullptr operation"); | 
|  | 11751 | assert(RHSTy->isNullPtrType() && "missing pointer conversion"); | 
|  | 11752 | // C++11 [expr.rel]p4, [expr.eq]p3: If two operands of type std::nullptr_t | 
|  | 11753 | // are compared, the result is true of the operator is <=, >= or ==, and | 
|  | 11754 | // false otherwise. | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11755 | return Success(CCR::Equal, E); | 
| Richard Smith | ab44d9b | 2012-02-14 22:35:28 +0000 | [diff] [blame] | 11756 | } | 
|  | 11757 |  | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11758 | return DoAfter(); | 
|  | 11759 | } | 
|  | 11760 |  | 
|  | 11761 | bool RecordExprEvaluator::VisitBinCmp(const BinaryOperator *E) { | 
|  | 11762 | if (!CheckLiteralType(Info, E)) | 
|  | 11763 | return false; | 
|  | 11764 |  | 
|  | 11765 | auto OnSuccess = [&](ComparisonCategoryResult ResKind, | 
|  | 11766 | const BinaryOperator *E) { | 
|  | 11767 | // Evaluation succeeded. Lookup the information for the comparison category | 
|  | 11768 | // type and fetch the VarDecl for the result. | 
|  | 11769 | const ComparisonCategoryInfo &CmpInfo = | 
|  | 11770 | Info.Ctx.CompCategories.getInfoForType(E->getType()); | 
|  | 11771 | const VarDecl *VD = | 
|  | 11772 | CmpInfo.getValueInfo(CmpInfo.makeWeakResult(ResKind))->VD; | 
|  | 11773 | // Check and evaluate the result as a constant expression. | 
|  | 11774 | LValue LV; | 
|  | 11775 | LV.set(VD); | 
|  | 11776 | if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) | 
|  | 11777 | return false; | 
|  | 11778 | return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result); | 
|  | 11779 | }; | 
|  | 11780 | return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() { | 
|  | 11781 | return ExprEvaluatorBaseTy::VisitBinCmp(E); | 
|  | 11782 | }); | 
|  | 11783 | } | 
|  | 11784 |  | 
|  | 11785 | bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { | 
|  | 11786 | // We don't call noteFailure immediately because the assignment happens after | 
|  | 11787 | // we evaluate LHS and RHS. | 
|  | 11788 | if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp()) | 
|  | 11789 | return Error(E); | 
|  | 11790 |  | 
|  | 11791 | DelayedNoteFailureRAII MaybeNoteFailureLater(Info, E->isAssignmentOp()); | 
|  | 11792 | if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E)) | 
|  | 11793 | return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E); | 
|  | 11794 |  | 
|  | 11795 | assert((!E->getLHS()->getType()->isIntegralOrEnumerationType() || | 
|  | 11796 | !E->getRHS()->getType()->isIntegralOrEnumerationType()) && | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11797 | "DataRecursiveIntBinOpEvaluator should have handled integral types"); | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11798 |  | 
|  | 11799 | if (E->isComparisonOp()) { | 
|  | 11800 | // Evaluate builtin binary comparisons by evaluating them as C++2a three-way | 
|  | 11801 | // comparisons and then translating the result. | 
|  | 11802 | auto OnSuccess = [&](ComparisonCategoryResult ResKind, | 
|  | 11803 | const BinaryOperator *E) { | 
|  | 11804 | using CCR = ComparisonCategoryResult; | 
|  | 11805 | bool IsEqual   = ResKind == CCR::Equal, | 
|  | 11806 | IsLess    = ResKind == CCR::Less, | 
|  | 11807 | IsGreater = ResKind == CCR::Greater; | 
|  | 11808 | auto Op = E->getOpcode(); | 
|  | 11809 | switch (Op) { | 
|  | 11810 | default: | 
|  | 11811 | llvm_unreachable("unsupported binary operator"); | 
|  | 11812 | case BO_EQ: | 
|  | 11813 | case BO_NE: | 
|  | 11814 | return Success(IsEqual == (Op == BO_EQ), E); | 
|  | 11815 | case BO_LT: return Success(IsLess, E); | 
|  | 11816 | case BO_GT: return Success(IsGreater, E); | 
|  | 11817 | case BO_LE: return Success(IsEqual || IsLess, E); | 
|  | 11818 | case BO_GE: return Success(IsEqual || IsGreater, E); | 
|  | 11819 | } | 
|  | 11820 | }; | 
|  | 11821 | return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() { | 
|  | 11822 | return ExprEvaluatorBaseTy::VisitBinaryOperator(E); | 
|  | 11823 | }); | 
|  | 11824 | } | 
|  | 11825 |  | 
|  | 11826 | QualType LHSTy = E->getLHS()->getType(); | 
|  | 11827 | QualType RHSTy = E->getRHS()->getType(); | 
|  | 11828 |  | 
|  | 11829 | if (LHSTy->isPointerType() && RHSTy->isPointerType() && | 
|  | 11830 | E->getOpcode() == BO_Sub) { | 
|  | 11831 | LValue LHSValue, RHSValue; | 
|  | 11832 |  | 
|  | 11833 | bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info); | 
|  | 11834 | if (!LHSOK && !Info.noteFailure()) | 
|  | 11835 | return false; | 
|  | 11836 |  | 
|  | 11837 | if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) | 
|  | 11838 | return false; | 
|  | 11839 |  | 
|  | 11840 | // Reject differing bases from the normal codepath; we special-case | 
|  | 11841 | // comparisons to null. | 
|  | 11842 | if (!HasSameBase(LHSValue, RHSValue)) { | 
|  | 11843 | // Handle &&A - &&B. | 
|  | 11844 | if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero()) | 
|  | 11845 | return Error(E); | 
|  | 11846 | const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr *>(); | 
|  | 11847 | const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr *>(); | 
|  | 11848 | if (!LHSExpr || !RHSExpr) | 
|  | 11849 | return Error(E); | 
|  | 11850 | const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr); | 
|  | 11851 | const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr); | 
|  | 11852 | if (!LHSAddrExpr || !RHSAddrExpr) | 
|  | 11853 | return Error(E); | 
|  | 11854 | // Make sure both labels come from the same function. | 
|  | 11855 | if (LHSAddrExpr->getLabel()->getDeclContext() != | 
|  | 11856 | RHSAddrExpr->getLabel()->getDeclContext()) | 
|  | 11857 | return Error(E); | 
|  | 11858 | return Success(APValue(LHSAddrExpr, RHSAddrExpr), E); | 
|  | 11859 | } | 
|  | 11860 | const CharUnits &LHSOffset = LHSValue.getLValueOffset(); | 
|  | 11861 | const CharUnits &RHSOffset = RHSValue.getLValueOffset(); | 
|  | 11862 |  | 
|  | 11863 | SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator(); | 
|  | 11864 | SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator(); | 
|  | 11865 |  | 
|  | 11866 | // C++11 [expr.add]p6: | 
|  | 11867 | //   Unless both pointers point to elements of the same array object, or | 
|  | 11868 | //   one past the last element of the array object, the behavior is | 
|  | 11869 | //   undefined. | 
|  | 11870 | if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && | 
|  | 11871 | !AreElementsOfSameArray(getType(LHSValue.Base), LHSDesignator, | 
|  | 11872 | RHSDesignator)) | 
|  | 11873 | Info.CCEDiag(E, diag::note_constexpr_pointer_subtraction_not_same_array); | 
|  | 11874 |  | 
|  | 11875 | QualType Type = E->getLHS()->getType(); | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 11876 | QualType ElementType = Type->castAs<PointerType>()->getPointeeType(); | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 11877 |  | 
|  | 11878 | CharUnits ElementSize; | 
|  | 11879 | if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize)) | 
|  | 11880 | return false; | 
|  | 11881 |  | 
|  | 11882 | // As an extension, a type may have zero size (empty struct or union in | 
|  | 11883 | // C, array of zero length). Pointer subtraction in such cases has | 
|  | 11884 | // undefined behavior, so is not constant. | 
|  | 11885 | if (ElementSize.isZero()) { | 
|  | 11886 | Info.FFDiag(E, diag::note_constexpr_pointer_subtraction_zero_size) | 
|  | 11887 | << ElementType; | 
|  | 11888 | return false; | 
|  | 11889 | } | 
|  | 11890 |  | 
|  | 11891 | // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime, | 
|  | 11892 | // and produce incorrect results when it overflows. Such behavior | 
|  | 11893 | // appears to be non-conforming, but is common, so perhaps we should | 
|  | 11894 | // assume the standard intended for such cases to be undefined behavior | 
|  | 11895 | // and check for them. | 
|  | 11896 |  | 
|  | 11897 | // Compute (LHSOffset - RHSOffset) / Size carefully, checking for | 
|  | 11898 | // overflow in the final conversion to ptrdiff_t. | 
|  | 11899 | APSInt LHS(llvm::APInt(65, (int64_t)LHSOffset.getQuantity(), true), false); | 
|  | 11900 | APSInt RHS(llvm::APInt(65, (int64_t)RHSOffset.getQuantity(), true), false); | 
|  | 11901 | APSInt ElemSize(llvm::APInt(65, (int64_t)ElementSize.getQuantity(), true), | 
|  | 11902 | false); | 
|  | 11903 | APSInt TrueResult = (LHS - RHS) / ElemSize; | 
|  | 11904 | APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E->getType())); | 
|  | 11905 |  | 
|  | 11906 | if (Result.extend(65) != TrueResult && | 
|  | 11907 | !HandleOverflow(Info, E, TrueResult, E->getType())) | 
|  | 11908 | return false; | 
|  | 11909 | return Success(Result, E); | 
|  | 11910 | } | 
|  | 11911 |  | 
| Argyrios Kyrtzidis | 57595e4 | 2012-03-15 18:07:16 +0000 | [diff] [blame] | 11912 | return ExprEvaluatorBaseTy::VisitBinaryOperator(E); | 
| Anders Carlsson | 9c18165 | 2008-07-08 14:35:21 +0000 | [diff] [blame] | 11913 | } | 
|  | 11914 |  | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11915 | /// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with | 
|  | 11916 | /// a result as the expression's type. | 
|  | 11917 | bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( | 
|  | 11918 | const UnaryExprOrTypeTraitExpr *E) { | 
|  | 11919 | switch(E->getKind()) { | 
| Richard Smith | 6822bd7 | 2018-10-26 19:26:45 +0000 | [diff] [blame] | 11920 | case UETT_PreferredAlignOf: | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11921 | case UETT_AlignOf: { | 
| Chris Lattner | 24aeeab | 2009-01-24 21:09:06 +0000 | [diff] [blame] | 11922 | if (E->isArgumentType()) | 
| Richard Smith | 6822bd7 | 2018-10-26 19:26:45 +0000 | [diff] [blame] | 11923 | return Success(GetAlignOfType(Info, E->getArgumentType(), E->getKind()), | 
|  | 11924 | E); | 
| Chris Lattner | 24aeeab | 2009-01-24 21:09:06 +0000 | [diff] [blame] | 11925 | else | 
| Richard Smith | 6822bd7 | 2018-10-26 19:26:45 +0000 | [diff] [blame] | 11926 | return Success(GetAlignOfExpr(Info, E->getArgumentExpr(), E->getKind()), | 
|  | 11927 | E); | 
| Chris Lattner | 24aeeab | 2009-01-24 21:09:06 +0000 | [diff] [blame] | 11928 | } | 
| Eli Friedman | 6400433 | 2009-03-23 04:38:34 +0000 | [diff] [blame] | 11929 |  | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11930 | case UETT_VecStep: { | 
|  | 11931 | QualType Ty = E->getTypeOfArgument(); | 
| Sebastian Redl | 6f28289 | 2008-11-11 17:56:53 +0000 | [diff] [blame] | 11932 |  | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11933 | if (Ty->isVectorType()) { | 
| Ted Kremenek | 2883175 | 2012-08-23 20:46:57 +0000 | [diff] [blame] | 11934 | unsigned n = Ty->castAs<VectorType>()->getNumElements(); | 
| Eli Friedman | 6400433 | 2009-03-23 04:38:34 +0000 | [diff] [blame] | 11935 |  | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11936 | // The vec_step built-in functions that take a 3-component | 
|  | 11937 | // vector return 4. (OpenCL 1.1 spec 6.11.12) | 
|  | 11938 | if (n == 3) | 
|  | 11939 | n = 4; | 
| Eli Friedman | 2aa38fe | 2009-01-24 22:19:05 +0000 | [diff] [blame] | 11940 |  | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11941 | return Success(n, E); | 
|  | 11942 | } else | 
|  | 11943 | return Success(1, E); | 
|  | 11944 | } | 
|  | 11945 |  | 
|  | 11946 | case UETT_SizeOf: { | 
|  | 11947 | QualType SrcTy = E->getTypeOfArgument(); | 
|  | 11948 | // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, | 
|  | 11949 | //   the result is the size of the referenced type." | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11950 | if (const ReferenceType *Ref = SrcTy->getAs<ReferenceType>()) | 
|  | 11951 | SrcTy = Ref->getPointeeType(); | 
|  | 11952 |  | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 11953 | CharUnits Sizeof; | 
| Richard Smith | 17100ba | 2012-02-16 02:46:34 +0000 | [diff] [blame] | 11954 | if (!HandleSizeof(Info, E->getExprLoc(), SrcTy, Sizeof)) | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11955 | return false; | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 11956 | return Success(Sizeof, E); | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11957 | } | 
| Alexey Bataev | 0039651 | 2015-07-02 03:40:19 +0000 | [diff] [blame] | 11958 | case UETT_OpenMPRequiredSimdAlign: | 
|  | 11959 | assert(E->isArgumentType()); | 
|  | 11960 | return Success( | 
|  | 11961 | Info.Ctx.toCharUnitsFromBits( | 
|  | 11962 | Info.Ctx.getOpenMPDefaultSimdAlign(E->getArgumentType())) | 
|  | 11963 | .getQuantity(), | 
|  | 11964 | E); | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 11965 | } | 
|  | 11966 |  | 
|  | 11967 | llvm_unreachable("unknown expr/type trait"); | 
| Chris Lattner | f8d7f72 | 2008-07-11 21:24:13 +0000 | [diff] [blame] | 11968 | } | 
|  | 11969 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 11970 | bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11971 | CharUnits Result; | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 11972 | unsigned n = OOE->getNumComponents(); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11973 | if (n == 0) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 11974 | return Error(OOE); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 11975 | QualType CurrentType = OOE->getTypeSourceInfo()->getType(); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11976 | for (unsigned i = 0; i != n; ++i) { | 
| James Y Knight | 7281c35 | 2015-12-29 22:31:18 +0000 | [diff] [blame] | 11977 | OffsetOfNode ON = OOE->getComponent(i); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11978 | switch (ON.getKind()) { | 
| James Y Knight | 7281c35 | 2015-12-29 22:31:18 +0000 | [diff] [blame] | 11979 | case OffsetOfNode::Array: { | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 11980 | const Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex()); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11981 | APSInt IdxResult; | 
|  | 11982 | if (!EvaluateInteger(Idx, IdxResult, Info)) | 
|  | 11983 | return false; | 
|  | 11984 | const ArrayType *AT = Info.Ctx.getAsArrayType(CurrentType); | 
|  | 11985 | if (!AT) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 11986 | return Error(OOE); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11987 | CurrentType = AT->getElementType(); | 
|  | 11988 | CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(CurrentType); | 
|  | 11989 | Result += IdxResult.getSExtValue() * ElementSize; | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 11990 | break; | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11991 | } | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 11992 |  | 
| James Y Knight | 7281c35 | 2015-12-29 22:31:18 +0000 | [diff] [blame] | 11993 | case OffsetOfNode::Field: { | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11994 | FieldDecl *MemberDecl = ON.getField(); | 
|  | 11995 | const RecordType *RT = CurrentType->getAs<RecordType>(); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 11996 | if (!RT) | 
|  | 11997 | return Error(OOE); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 11998 | RecordDecl *RD = RT->getDecl(); | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 11999 | if (RD->isInvalidDecl()) return false; | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 12000 | const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); | 
| John McCall | 4e81961 | 2011-01-20 07:57:12 +0000 | [diff] [blame] | 12001 | unsigned i = MemberDecl->getFieldIndex(); | 
| Douglas Gregor | d170206 | 2010-04-29 00:18:15 +0000 | [diff] [blame] | 12002 | assert(i < RL.getFieldCount() && "offsetof field in wrong type"); | 
| Ken Dyck | 86a7fcc | 2011-01-18 01:56:16 +0000 | [diff] [blame] | 12003 | Result += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i)); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 12004 | CurrentType = MemberDecl->getType().getNonReferenceType(); | 
|  | 12005 | break; | 
|  | 12006 | } | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12007 |  | 
| James Y Knight | 7281c35 | 2015-12-29 22:31:18 +0000 | [diff] [blame] | 12008 | case OffsetOfNode::Identifier: | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 12009 | llvm_unreachable("dependent __builtin_offsetof"); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12010 |  | 
| James Y Knight | 7281c35 | 2015-12-29 22:31:18 +0000 | [diff] [blame] | 12011 | case OffsetOfNode::Base: { | 
| Douglas Gregor | d170206 | 2010-04-29 00:18:15 +0000 | [diff] [blame] | 12012 | CXXBaseSpecifier *BaseSpec = ON.getBase(); | 
|  | 12013 | if (BaseSpec->isVirtual()) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12014 | return Error(OOE); | 
| Douglas Gregor | d170206 | 2010-04-29 00:18:15 +0000 | [diff] [blame] | 12015 |  | 
|  | 12016 | // Find the layout of the class whose base we are looking into. | 
|  | 12017 | const RecordType *RT = CurrentType->getAs<RecordType>(); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12018 | if (!RT) | 
|  | 12019 | return Error(OOE); | 
| Douglas Gregor | d170206 | 2010-04-29 00:18:15 +0000 | [diff] [blame] | 12020 | RecordDecl *RD = RT->getDecl(); | 
| John McCall | d7bca76 | 2012-05-01 00:38:49 +0000 | [diff] [blame] | 12021 | if (RD->isInvalidDecl()) return false; | 
| Douglas Gregor | d170206 | 2010-04-29 00:18:15 +0000 | [diff] [blame] | 12022 | const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); | 
|  | 12023 |  | 
|  | 12024 | // Find the base class itself. | 
|  | 12025 | CurrentType = BaseSpec->getType(); | 
|  | 12026 | const RecordType *BaseRT = CurrentType->getAs<RecordType>(); | 
|  | 12027 | if (!BaseRT) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12028 | return Error(OOE); | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 12029 |  | 
| Douglas Gregor | d170206 | 2010-04-29 00:18:15 +0000 | [diff] [blame] | 12030 | // Add the offset to the base. | 
| Ken Dyck | 02155cb | 2011-01-26 02:17:08 +0000 | [diff] [blame] | 12031 | Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl())); | 
| Douglas Gregor | d170206 | 2010-04-29 00:18:15 +0000 | [diff] [blame] | 12032 | break; | 
|  | 12033 | } | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 12034 | } | 
|  | 12035 | } | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12036 | return Success(Result, OOE); | 
| Douglas Gregor | 882211c | 2010-04-28 22:16:22 +0000 | [diff] [blame] | 12037 | } | 
|  | 12038 |  | 
| Chris Lattner | e13042c | 2008-07-11 19:10:17 +0000 | [diff] [blame] | 12039 | bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12040 | switch (E->getOpcode()) { | 
|  | 12041 | default: | 
|  | 12042 | // Address, indirect, pre/post inc/dec, etc are not valid constant exprs. | 
|  | 12043 | // See C99 6.6p3. | 
|  | 12044 | return Error(E); | 
|  | 12045 | case UO_Extension: | 
|  | 12046 | // FIXME: Should extension allow i-c-e extension expressions in its scope? | 
|  | 12047 | // If so, we could clear the diagnostic ID. | 
|  | 12048 | return Visit(E->getSubExpr()); | 
|  | 12049 | case UO_Plus: | 
|  | 12050 | // The result is just the value. | 
|  | 12051 | return Visit(E->getSubExpr()); | 
|  | 12052 | case UO_Minus: { | 
|  | 12053 | if (!Visit(E->getSubExpr())) | 
| Malcolm Parsons | fab3680 | 2018-04-16 08:31:08 +0000 | [diff] [blame] | 12054 | return false; | 
|  | 12055 | if (!Result.isInt()) return Error(E); | 
|  | 12056 | const APSInt &Value = Result.getInt(); | 
|  | 12057 | if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow() && | 
|  | 12058 | !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), | 
|  | 12059 | E->getType())) | 
|  | 12060 | return false; | 
| Richard Smith | fe80003 | 2012-01-31 04:08:20 +0000 | [diff] [blame] | 12061 | return Success(-Value, E); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12062 | } | 
|  | 12063 | case UO_Not: { | 
|  | 12064 | if (!Visit(E->getSubExpr())) | 
|  | 12065 | return false; | 
|  | 12066 | if (!Result.isInt()) return Error(E); | 
|  | 12067 | return Success(~Result.getInt(), E); | 
|  | 12068 | } | 
|  | 12069 | case UO_LNot: { | 
| Eli Friedman | 5a332ea | 2008-11-13 06:09:17 +0000 | [diff] [blame] | 12070 | bool bres; | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 12071 | if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info)) | 
| Eli Friedman | 5a332ea | 2008-11-13 06:09:17 +0000 | [diff] [blame] | 12072 | return false; | 
| Daniel Dunbar | 8aafc89 | 2009-02-19 09:06:44 +0000 | [diff] [blame] | 12073 | return Success(!bres, E); | 
| Eli Friedman | 5a332ea | 2008-11-13 06:09:17 +0000 | [diff] [blame] | 12074 | } | 
| Anders Carlsson | 9c18165 | 2008-07-08 14:35:21 +0000 | [diff] [blame] | 12075 | } | 
| Anders Carlsson | 9c18165 | 2008-07-08 14:35:21 +0000 | [diff] [blame] | 12076 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12077 |  | 
| Chris Lattner | 477c4be | 2008-07-12 01:15:53 +0000 | [diff] [blame] | 12078 | /// HandleCast - This is used to evaluate implicit or explicit casts where the | 
|  | 12079 | /// result type is integer. | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12080 | bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { | 
|  | 12081 | const Expr *SubExpr = E->getSubExpr(); | 
| Anders Carlsson | 27b8c5c | 2008-11-30 18:14:57 +0000 | [diff] [blame] | 12082 | QualType DestType = E->getType(); | 
| Daniel Dunbar | cf04aa1 | 2009-02-19 22:16:29 +0000 | [diff] [blame] | 12083 | QualType SrcType = SubExpr->getType(); | 
| Anders Carlsson | 27b8c5c | 2008-11-30 18:14:57 +0000 | [diff] [blame] | 12084 |  | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12085 | switch (E->getCastKind()) { | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12086 | case CK_BaseToDerived: | 
|  | 12087 | case CK_DerivedToBase: | 
|  | 12088 | case CK_UncheckedDerivedToBase: | 
|  | 12089 | case CK_Dynamic: | 
|  | 12090 | case CK_ToUnion: | 
|  | 12091 | case CK_ArrayToPointerDecay: | 
|  | 12092 | case CK_FunctionToPointerDecay: | 
|  | 12093 | case CK_NullToPointer: | 
|  | 12094 | case CK_NullToMemberPointer: | 
|  | 12095 | case CK_BaseToDerivedMemberPointer: | 
|  | 12096 | case CK_DerivedToBaseMemberPointer: | 
| John McCall | c62bb39 | 2012-02-15 01:22:51 +0000 | [diff] [blame] | 12097 | case CK_ReinterpretMemberPointer: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12098 | case CK_ConstructorConversion: | 
|  | 12099 | case CK_IntegralToPointer: | 
|  | 12100 | case CK_ToVoid: | 
|  | 12101 | case CK_VectorSplat: | 
|  | 12102 | case CK_IntegralToFloating: | 
|  | 12103 | case CK_FloatingCast: | 
| John McCall | 9320b87 | 2011-09-09 05:25:32 +0000 | [diff] [blame] | 12104 | case CK_CPointerToObjCPointerCast: | 
|  | 12105 | case CK_BlockPointerToObjCPointerCast: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12106 | case CK_AnyPointerToBlockPointerCast: | 
|  | 12107 | case CK_ObjCObjectLValueCast: | 
|  | 12108 | case CK_FloatingRealToComplex: | 
|  | 12109 | case CK_FloatingComplexToReal: | 
|  | 12110 | case CK_FloatingComplexCast: | 
|  | 12111 | case CK_FloatingComplexToIntegralComplex: | 
|  | 12112 | case CK_IntegralRealToComplex: | 
|  | 12113 | case CK_IntegralComplexCast: | 
|  | 12114 | case CK_IntegralComplexToFloatingComplex: | 
| Eli Friedman | 34866c7 | 2012-08-31 00:14:07 +0000 | [diff] [blame] | 12115 | case CK_BuiltinFnToFnPtr: | 
| Andrew Savonichev | b555b76 | 2018-10-23 15:19:20 +0000 | [diff] [blame] | 12116 | case CK_ZeroToOCLOpaqueType: | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 12117 | case CK_NonAtomicToAtomic: | 
| David Tweed | e146832 | 2013-12-11 13:39:46 +0000 | [diff] [blame] | 12118 | case CK_AddressSpaceConversion: | 
| Yaxun Liu | 0bc4b2d | 2016-07-28 19:26:30 +0000 | [diff] [blame] | 12119 | case CK_IntToOCLSampler: | 
| Leonard Chan | 99bda37 | 2018-10-15 16:07:02 +0000 | [diff] [blame] | 12120 | case CK_FixedPointCast: | 
| Leonard Chan | 8f7caae | 2019-03-06 00:28:43 +0000 | [diff] [blame] | 12121 | case CK_IntegralToFixedPoint: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12122 | llvm_unreachable("invalid cast kind for integral value"); | 
|  | 12123 |  | 
| Eli Friedman | 9faf2f9 | 2011-03-25 19:07:11 +0000 | [diff] [blame] | 12124 | case CK_BitCast: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12125 | case CK_Dependent: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12126 | case CK_LValueBitCast: | 
| John McCall | 2d637d2 | 2011-09-10 06:18:15 +0000 | [diff] [blame] | 12127 | case CK_ARCProduceObject: | 
|  | 12128 | case CK_ARCConsumeObject: | 
|  | 12129 | case CK_ARCReclaimReturnedObject: | 
|  | 12130 | case CK_ARCExtendBlockObject: | 
| Douglas Gregor | ed90df3 | 2012-02-22 05:02:47 +0000 | [diff] [blame] | 12131 | case CK_CopyAndAutoreleaseBlockObject: | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12132 | return Error(E); | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12133 |  | 
| Richard Smith | 4ef685b | 2012-01-17 21:17:26 +0000 | [diff] [blame] | 12134 | case CK_UserDefinedConversion: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12135 | case CK_LValueToRValue: | 
| David Chisnall | fa35df6 | 2012-01-16 17:27:18 +0000 | [diff] [blame] | 12136 | case CK_AtomicToNonAtomic: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12137 | case CK_NoOp: | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 12138 | case CK_LValueToRValueBitCast: | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 12139 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12140 |  | 
|  | 12141 | case CK_MemberPointerToBoolean: | 
|  | 12142 | case CK_PointerToBoolean: | 
|  | 12143 | case CK_IntegralToBoolean: | 
|  | 12144 | case CK_FloatingToBoolean: | 
| George Burgess IV | df1ed00 | 2016-01-13 01:52:39 +0000 | [diff] [blame] | 12145 | case CK_BooleanToSignedIntegral: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12146 | case CK_FloatingComplexToBoolean: | 
|  | 12147 | case CK_IntegralComplexToBoolean: { | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12148 | bool BoolResult; | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 12149 | if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info)) | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12150 | return false; | 
| George Burgess IV | df1ed00 | 2016-01-13 01:52:39 +0000 | [diff] [blame] | 12151 | uint64_t IntResult = BoolResult; | 
|  | 12152 | if (BoolResult && E->getCastKind() == CK_BooleanToSignedIntegral) | 
|  | 12153 | IntResult = (uint64_t)-1; | 
|  | 12154 | return Success(IntResult, E); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12155 | } | 
|  | 12156 |  | 
| Leonard Chan | 8f7caae | 2019-03-06 00:28:43 +0000 | [diff] [blame] | 12157 | case CK_FixedPointToIntegral: { | 
|  | 12158 | APFixedPoint Src(Info.Ctx.getFixedPointSemantics(SrcType)); | 
|  | 12159 | if (!EvaluateFixedPoint(SubExpr, Src, Info)) | 
|  | 12160 | return false; | 
|  | 12161 | bool Overflowed; | 
|  | 12162 | llvm::APSInt Result = Src.convertToInt( | 
|  | 12163 | Info.Ctx.getIntWidth(DestType), | 
|  | 12164 | DestType->isSignedIntegerOrEnumerationType(), &Overflowed); | 
|  | 12165 | if (Overflowed && !HandleOverflow(Info, E, Result, DestType)) | 
|  | 12166 | return false; | 
|  | 12167 | return Success(Result, E); | 
|  | 12168 | } | 
|  | 12169 |  | 
| Leonard Chan | b4ba467 | 2018-10-23 17:55:35 +0000 | [diff] [blame] | 12170 | case CK_FixedPointToBoolean: { | 
|  | 12171 | // Unsigned padding does not affect this. | 
|  | 12172 | APValue Val; | 
|  | 12173 | if (!Evaluate(Val, Info, SubExpr)) | 
|  | 12174 | return false; | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 12175 | return Success(Val.getFixedPoint().getBoolValue(), E); | 
| Leonard Chan | b4ba467 | 2018-10-23 17:55:35 +0000 | [diff] [blame] | 12176 | } | 
|  | 12177 |  | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12178 | case CK_IntegralCast: { | 
| Chris Lattner | 477c4be | 2008-07-12 01:15:53 +0000 | [diff] [blame] | 12179 | if (!Visit(SubExpr)) | 
| Chris Lattner | e13042c | 2008-07-11 19:10:17 +0000 | [diff] [blame] | 12180 | return false; | 
| Daniel Dunbar | b6f953e | 2009-01-29 06:16:07 +0000 | [diff] [blame] | 12181 |  | 
| Eli Friedman | 742421e | 2009-02-20 01:15:07 +0000 | [diff] [blame] | 12182 | if (!Result.isInt()) { | 
| Eli Friedman | fd5e54d | 2012-01-04 23:13:47 +0000 | [diff] [blame] | 12183 | // Allow casts of address-of-label differences if they are no-ops | 
|  | 12184 | // or narrowing.  (The narrowing case isn't actually guaranteed to | 
|  | 12185 | // be constant-evaluatable except in some narrow cases which are hard | 
|  | 12186 | // to detect here.  We let it through on the assumption the user knows | 
|  | 12187 | // what they are doing.) | 
|  | 12188 | if (Result.isAddrLabelDiff()) | 
|  | 12189 | return Info.Ctx.getTypeSize(DestType) <= Info.Ctx.getTypeSize(SrcType); | 
| Eli Friedman | 742421e | 2009-02-20 01:15:07 +0000 | [diff] [blame] | 12190 | // Only allow casts of lvalues if they are lossless. | 
|  | 12191 | return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType); | 
|  | 12192 | } | 
| Daniel Dunbar | ca097ad | 2009-02-19 20:17:33 +0000 | [diff] [blame] | 12193 |  | 
| Richard Smith | 911e142 | 2012-01-30 22:27:01 +0000 | [diff] [blame] | 12194 | return Success(HandleIntToIntCast(Info, E, DestType, SrcType, | 
|  | 12195 | Result.getInt()), E); | 
| Chris Lattner | 477c4be | 2008-07-12 01:15:53 +0000 | [diff] [blame] | 12196 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12197 |  | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12198 | case CK_PointerToIntegral: { | 
| Richard Smith | 6d6ecc3 | 2011-12-12 12:46:16 +0000 | [diff] [blame] | 12199 | CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; | 
|  | 12200 |  | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 12201 | LValue LV; | 
| Chris Lattner | cdf34e7 | 2008-07-11 22:52:41 +0000 | [diff] [blame] | 12202 | if (!EvaluatePointer(SubExpr, LV, Info)) | 
| Chris Lattner | e13042c | 2008-07-11 19:10:17 +0000 | [diff] [blame] | 12203 | return false; | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12204 |  | 
| Daniel Dunbar | 1c8560d | 2009-02-19 22:24:01 +0000 | [diff] [blame] | 12205 | if (LV.getLValueBase()) { | 
|  | 12206 | // Only allow based lvalue casts if they are lossless. | 
| Richard Smith | 911e142 | 2012-01-30 22:27:01 +0000 | [diff] [blame] | 12207 | // FIXME: Allow a larger integer size than the pointer size, and allow | 
|  | 12208 | // narrowing back down to pointer width in subsequent integral casts. | 
|  | 12209 | // FIXME: Check integer type's active bits, not its type size. | 
| Daniel Dunbar | 1c8560d | 2009-02-19 22:24:01 +0000 | [diff] [blame] | 12210 | if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType)) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12211 | return Error(E); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12212 |  | 
| Richard Smith | cf74da7 | 2011-11-16 07:18:12 +0000 | [diff] [blame] | 12213 | LV.Designator.setInvalid(); | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 12214 | LV.moveInto(Result); | 
| Daniel Dunbar | 1c8560d | 2009-02-19 22:24:01 +0000 | [diff] [blame] | 12215 | return true; | 
|  | 12216 | } | 
|  | 12217 |  | 
| Hans Wennborg | dd1ea8a | 2019-03-06 10:26:19 +0000 | [diff] [blame] | 12218 | APSInt AsInt; | 
|  | 12219 | APValue V; | 
|  | 12220 | LV.moveInto(V); | 
|  | 12221 | if (!V.toIntegralConstant(AsInt, SrcType, Info.Ctx)) | 
|  | 12222 | llvm_unreachable("Can't cast this!"); | 
| Yaxun Liu | 402804b | 2016-12-15 08:09:08 +0000 | [diff] [blame] | 12223 |  | 
| Richard Smith | 911e142 | 2012-01-30 22:27:01 +0000 | [diff] [blame] | 12224 | return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); | 
| Anders Carlsson | b5ad021 | 2008-07-08 14:30:00 +0000 | [diff] [blame] | 12225 | } | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12226 |  | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12227 | case CK_IntegralComplexToReal: { | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12228 | ComplexValue C; | 
| Eli Friedman | d3a5a9d | 2009-04-22 19:23:09 +0000 | [diff] [blame] | 12229 | if (!EvaluateComplex(SubExpr, C, Info)) | 
|  | 12230 | return false; | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12231 | return Success(C.getComplexIntReal(), E); | 
| Eli Friedman | d3a5a9d | 2009-04-22 19:23:09 +0000 | [diff] [blame] | 12232 | } | 
| Eli Friedman | c2b5017 | 2009-02-22 11:46:18 +0000 | [diff] [blame] | 12233 |  | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12234 | case CK_FloatingToIntegral: { | 
|  | 12235 | APFloat F(0.0); | 
|  | 12236 | if (!EvaluateFloat(SubExpr, F, Info)) | 
|  | 12237 | return false; | 
| Chris Lattner | 477c4be | 2008-07-12 01:15:53 +0000 | [diff] [blame] | 12238 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 12239 | APSInt Value; | 
|  | 12240 | if (!HandleFloatToIntCast(Info, E, SrcType, F, DestType, Value)) | 
|  | 12241 | return false; | 
|  | 12242 | return Success(Value, E); | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12243 | } | 
|  | 12244 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12245 |  | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12246 | llvm_unreachable("unknown cast resulting in integral value"); | 
| Anders Carlsson | 9c18165 | 2008-07-08 14:35:21 +0000 | [diff] [blame] | 12247 | } | 
| Anders Carlsson | b5ad021 | 2008-07-08 14:30:00 +0000 | [diff] [blame] | 12248 |  | 
| Eli Friedman | a1c7b6c | 2009-02-28 03:59:05 +0000 | [diff] [blame] | 12249 | bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { | 
|  | 12250 | if (E->getSubExpr()->getType()->isAnyComplexType()) { | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12251 | ComplexValue LV; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12252 | if (!EvaluateComplex(E->getSubExpr(), LV, Info)) | 
|  | 12253 | return false; | 
|  | 12254 | if (!LV.isComplexInt()) | 
|  | 12255 | return Error(E); | 
| Eli Friedman | a1c7b6c | 2009-02-28 03:59:05 +0000 | [diff] [blame] | 12256 | return Success(LV.getComplexIntReal(), E); | 
|  | 12257 | } | 
|  | 12258 |  | 
|  | 12259 | return Visit(E->getSubExpr()); | 
|  | 12260 | } | 
|  | 12261 |  | 
| Eli Friedman | 4e7a241 | 2009-02-27 04:45:43 +0000 | [diff] [blame] | 12262 | bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { | 
| Eli Friedman | a1c7b6c | 2009-02-28 03:59:05 +0000 | [diff] [blame] | 12263 | if (E->getSubExpr()->getType()->isComplexIntegerType()) { | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12264 | ComplexValue LV; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12265 | if (!EvaluateComplex(E->getSubExpr(), LV, Info)) | 
|  | 12266 | return false; | 
|  | 12267 | if (!LV.isComplexInt()) | 
|  | 12268 | return Error(E); | 
| Eli Friedman | a1c7b6c | 2009-02-28 03:59:05 +0000 | [diff] [blame] | 12269 | return Success(LV.getComplexIntImag(), E); | 
|  | 12270 | } | 
|  | 12271 |  | 
| Richard Smith | 4a67812 | 2011-10-24 18:44:57 +0000 | [diff] [blame] | 12272 | VisitIgnoredValue(E->getSubExpr()); | 
| Eli Friedman | 4e7a241 | 2009-02-27 04:45:43 +0000 | [diff] [blame] | 12273 | return Success(0, E); | 
|  | 12274 | } | 
|  | 12275 |  | 
| Douglas Gregor | 820ba7b | 2011-01-04 17:33:58 +0000 | [diff] [blame] | 12276 | bool IntExprEvaluator::VisitSizeOfPackExpr(const SizeOfPackExpr *E) { | 
|  | 12277 | return Success(E->getPackLength(), E); | 
|  | 12278 | } | 
|  | 12279 |  | 
| Sebastian Redl | 5f0180d | 2010-09-10 20:55:47 +0000 | [diff] [blame] | 12280 | bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { | 
|  | 12281 | return Success(E->getValue(), E); | 
|  | 12282 | } | 
|  | 12283 |  | 
| Saar Raz | 5d98ba6 | 2019-10-15 15:24:26 +0000 | [diff] [blame] | 12284 | bool IntExprEvaluator::VisitConceptSpecializationExpr( | 
|  | 12285 | const ConceptSpecializationExpr *E) { | 
|  | 12286 | return Success(E->isSatisfied(), E); | 
|  | 12287 | } | 
|  | 12288 |  | 
|  | 12289 |  | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 12290 | bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { | 
|  | 12291 | switch (E->getOpcode()) { | 
|  | 12292 | default: | 
|  | 12293 | // Invalid unary operators | 
|  | 12294 | return Error(E); | 
|  | 12295 | case UO_Plus: | 
|  | 12296 | // The result is just the value. | 
|  | 12297 | return Visit(E->getSubExpr()); | 
|  | 12298 | case UO_Minus: { | 
|  | 12299 | if (!Visit(E->getSubExpr())) return false; | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 12300 | if (!Result.isFixedPoint()) | 
|  | 12301 | return Error(E); | 
|  | 12302 | bool Overflowed; | 
|  | 12303 | APFixedPoint Negated = Result.getFixedPoint().negate(&Overflowed); | 
|  | 12304 | if (Overflowed && !HandleOverflow(Info, E, Negated, E->getType())) | 
|  | 12305 | return false; | 
|  | 12306 | return Success(Negated, E); | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 12307 | } | 
|  | 12308 | case UO_LNot: { | 
|  | 12309 | bool bres; | 
|  | 12310 | if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info)) | 
|  | 12311 | return false; | 
|  | 12312 | return Success(!bres, E); | 
|  | 12313 | } | 
|  | 12314 | } | 
|  | 12315 | } | 
|  | 12316 |  | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 12317 | bool FixedPointExprEvaluator::VisitCastExpr(const CastExpr *E) { | 
|  | 12318 | const Expr *SubExpr = E->getSubExpr(); | 
|  | 12319 | QualType DestType = E->getType(); | 
|  | 12320 | assert(DestType->isFixedPointType() && | 
|  | 12321 | "Expected destination type to be a fixed point type"); | 
|  | 12322 | auto DestFXSema = Info.Ctx.getFixedPointSemantics(DestType); | 
|  | 12323 |  | 
|  | 12324 | switch (E->getCastKind()) { | 
|  | 12325 | case CK_FixedPointCast: { | 
|  | 12326 | APFixedPoint Src(Info.Ctx.getFixedPointSemantics(SubExpr->getType())); | 
|  | 12327 | if (!EvaluateFixedPoint(SubExpr, Src, Info)) | 
|  | 12328 | return false; | 
|  | 12329 | bool Overflowed; | 
|  | 12330 | APFixedPoint Result = Src.convert(DestFXSema, &Overflowed); | 
|  | 12331 | if (Overflowed && !HandleOverflow(Info, E, Result, DestType)) | 
|  | 12332 | return false; | 
|  | 12333 | return Success(Result, E); | 
|  | 12334 | } | 
| Leonard Chan | 8f7caae | 2019-03-06 00:28:43 +0000 | [diff] [blame] | 12335 | case CK_IntegralToFixedPoint: { | 
|  | 12336 | APSInt Src; | 
|  | 12337 | if (!EvaluateInteger(SubExpr, Src, Info)) | 
|  | 12338 | return false; | 
|  | 12339 |  | 
|  | 12340 | bool Overflowed; | 
|  | 12341 | APFixedPoint IntResult = APFixedPoint::getFromIntValue( | 
|  | 12342 | Src, Info.Ctx.getFixedPointSemantics(DestType), &Overflowed); | 
|  | 12343 |  | 
|  | 12344 | if (Overflowed && !HandleOverflow(Info, E, IntResult, DestType)) | 
|  | 12345 | return false; | 
|  | 12346 |  | 
|  | 12347 | return Success(IntResult, E); | 
|  | 12348 | } | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 12349 | case CK_NoOp: | 
|  | 12350 | case CK_LValueToRValue: | 
|  | 12351 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
|  | 12352 | default: | 
|  | 12353 | return Error(E); | 
|  | 12354 | } | 
|  | 12355 | } | 
|  | 12356 |  | 
|  | 12357 | bool FixedPointExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { | 
|  | 12358 | const Expr *LHS = E->getLHS(); | 
|  | 12359 | const Expr *RHS = E->getRHS(); | 
|  | 12360 | FixedPointSemantics ResultFXSema = | 
|  | 12361 | Info.Ctx.getFixedPointSemantics(E->getType()); | 
|  | 12362 |  | 
|  | 12363 | APFixedPoint LHSFX(Info.Ctx.getFixedPointSemantics(LHS->getType())); | 
|  | 12364 | if (!EvaluateFixedPointOrInteger(LHS, LHSFX, Info)) | 
|  | 12365 | return false; | 
|  | 12366 | APFixedPoint RHSFX(Info.Ctx.getFixedPointSemantics(RHS->getType())); | 
|  | 12367 | if (!EvaluateFixedPointOrInteger(RHS, RHSFX, Info)) | 
|  | 12368 | return false; | 
|  | 12369 |  | 
|  | 12370 | switch (E->getOpcode()) { | 
|  | 12371 | case BO_Add: { | 
|  | 12372 | bool AddOverflow, ConversionOverflow; | 
|  | 12373 | APFixedPoint Result = LHSFX.add(RHSFX, &AddOverflow) | 
|  | 12374 | .convert(ResultFXSema, &ConversionOverflow); | 
|  | 12375 | if ((AddOverflow || ConversionOverflow) && | 
|  | 12376 | !HandleOverflow(Info, E, Result, E->getType())) | 
|  | 12377 | return false; | 
|  | 12378 | return Success(Result, E); | 
|  | 12379 | } | 
|  | 12380 | default: | 
|  | 12381 | return false; | 
|  | 12382 | } | 
|  | 12383 | llvm_unreachable("Should've exited before this"); | 
|  | 12384 | } | 
|  | 12385 |  | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 12386 | //===----------------------------------------------------------------------===// | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12387 | // Float Evaluation | 
|  | 12388 | //===----------------------------------------------------------------------===// | 
|  | 12389 |  | 
|  | 12390 | namespace { | 
| Benjamin Kramer | 26222b6 | 2009-11-28 19:03:38 +0000 | [diff] [blame] | 12391 | class FloatExprEvaluator | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 12392 | : public ExprEvaluatorBase<FloatExprEvaluator> { | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12393 | APFloat &Result; | 
|  | 12394 | public: | 
|  | 12395 | FloatExprEvaluator(EvalInfo &info, APFloat &result) | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12396 | : ExprEvaluatorBaseTy(info), Result(result) {} | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12397 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 12398 | bool Success(const APValue &V, const Expr *e) { | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12399 | Result = V.getFloat(); | 
|  | 12400 | return true; | 
|  | 12401 | } | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12402 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 12403 | bool ZeroInitialization(const Expr *E) { | 
| Richard Smith | 4ce706a | 2011-10-11 21:43:33 +0000 | [diff] [blame] | 12404 | Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); | 
|  | 12405 | return true; | 
|  | 12406 | } | 
|  | 12407 |  | 
| Chris Lattner | 4deaa4e | 2008-10-06 05:28:25 +0000 | [diff] [blame] | 12408 | bool VisitCallExpr(const CallExpr *E); | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12409 |  | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12410 | bool VisitUnaryOperator(const UnaryOperator *E); | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12411 | bool VisitBinaryOperator(const BinaryOperator *E); | 
|  | 12412 | bool VisitFloatingLiteral(const FloatingLiteral *E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12413 | bool VisitCastExpr(const CastExpr *E); | 
| Eli Friedman | c2b5017 | 2009-02-22 11:46:18 +0000 | [diff] [blame] | 12414 |  | 
| John McCall | b1fb0d3 | 2010-05-07 22:08:54 +0000 | [diff] [blame] | 12415 | bool VisitUnaryReal(const UnaryOperator *E); | 
|  | 12416 | bool VisitUnaryImag(const UnaryOperator *E); | 
| Eli Friedman | 449fe54 | 2009-03-23 04:56:01 +0000 | [diff] [blame] | 12417 |  | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 12418 | // FIXME: Missing: array subscript of vector, member of vector | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12419 | }; | 
|  | 12420 | } // end anonymous namespace | 
|  | 12421 |  | 
|  | 12422 | static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 12423 | assert(E->isRValue() && E->getType()->isRealFloatingType()); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12424 | return FloatExprEvaluator(Info, Result).Visit(E); | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12425 | } | 
|  | 12426 |  | 
| Jay Foad | 39c7980 | 2011-01-12 09:06:06 +0000 | [diff] [blame] | 12427 | static bool TryEvaluateBuiltinNaN(const ASTContext &Context, | 
| John McCall | 1629149 | 2010-02-28 13:00:19 +0000 | [diff] [blame] | 12428 | QualType ResultTy, | 
|  | 12429 | const Expr *Arg, | 
|  | 12430 | bool SNaN, | 
|  | 12431 | llvm::APFloat &Result) { | 
|  | 12432 | const StringLiteral *S = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts()); | 
|  | 12433 | if (!S) return false; | 
|  | 12434 |  | 
|  | 12435 | const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(ResultTy); | 
|  | 12436 |  | 
|  | 12437 | llvm::APInt fill; | 
|  | 12438 |  | 
|  | 12439 | // Treat empty strings as if they were zero. | 
|  | 12440 | if (S->getString().empty()) | 
|  | 12441 | fill = llvm::APInt(32, 0); | 
|  | 12442 | else if (S->getString().getAsInteger(0, fill)) | 
|  | 12443 | return false; | 
|  | 12444 |  | 
| Petar Jovanovic | d55ae6b | 2015-02-26 18:19:22 +0000 | [diff] [blame] | 12445 | if (Context.getTargetInfo().isNan2008()) { | 
|  | 12446 | if (SNaN) | 
|  | 12447 | Result = llvm::APFloat::getSNaN(Sem, false, &fill); | 
|  | 12448 | else | 
|  | 12449 | Result = llvm::APFloat::getQNaN(Sem, false, &fill); | 
|  | 12450 | } else { | 
|  | 12451 | // Prior to IEEE 754-2008, architectures were allowed to choose whether | 
|  | 12452 | // the first bit of their significand was set for qNaN or sNaN. MIPS chose | 
|  | 12453 | // a different encoding to what became a standard in 2008, and for pre- | 
|  | 12454 | // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as | 
|  | 12455 | // sNaN. This is now known as "legacy NaN" encoding. | 
|  | 12456 | if (SNaN) | 
|  | 12457 | Result = llvm::APFloat::getQNaN(Sem, false, &fill); | 
|  | 12458 | else | 
|  | 12459 | Result = llvm::APFloat::getSNaN(Sem, false, &fill); | 
|  | 12460 | } | 
|  | 12461 |  | 
| John McCall | 1629149 | 2010-02-28 13:00:19 +0000 | [diff] [blame] | 12462 | return true; | 
|  | 12463 | } | 
|  | 12464 |  | 
| Chris Lattner | 4deaa4e | 2008-10-06 05:28:25 +0000 | [diff] [blame] | 12465 | bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { | 
| Alp Toker | a724cff | 2013-12-28 21:59:02 +0000 | [diff] [blame] | 12466 | switch (E->getBuiltinCallee()) { | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12467 | default: | 
|  | 12468 | return ExprEvaluatorBaseTy::VisitCallExpr(E); | 
|  | 12469 |  | 
| Chris Lattner | 4deaa4e | 2008-10-06 05:28:25 +0000 | [diff] [blame] | 12470 | case Builtin::BI__builtin_huge_val: | 
|  | 12471 | case Builtin::BI__builtin_huge_valf: | 
|  | 12472 | case Builtin::BI__builtin_huge_vall: | 
| Benjamin Kramer | dfecbe9 | 2018-01-06 21:49:54 +0000 | [diff] [blame] | 12473 | case Builtin::BI__builtin_huge_valf128: | 
| Chris Lattner | 4deaa4e | 2008-10-06 05:28:25 +0000 | [diff] [blame] | 12474 | case Builtin::BI__builtin_inf: | 
|  | 12475 | case Builtin::BI__builtin_inff: | 
| Benjamin Kramer | dfecbe9 | 2018-01-06 21:49:54 +0000 | [diff] [blame] | 12476 | case Builtin::BI__builtin_infl: | 
|  | 12477 | case Builtin::BI__builtin_inff128: { | 
| Daniel Dunbar | 1be9f88 | 2008-10-14 05:41:12 +0000 | [diff] [blame] | 12478 | const llvm::fltSemantics &Sem = | 
|  | 12479 | Info.Ctx.getFloatTypeSemantics(E->getType()); | 
| Chris Lattner | 37346e0 | 2008-10-06 05:53:16 +0000 | [diff] [blame] | 12480 | Result = llvm::APFloat::getInf(Sem); | 
|  | 12481 | return true; | 
| Daniel Dunbar | 1be9f88 | 2008-10-14 05:41:12 +0000 | [diff] [blame] | 12482 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12483 |  | 
| John McCall | 1629149 | 2010-02-28 13:00:19 +0000 | [diff] [blame] | 12484 | case Builtin::BI__builtin_nans: | 
|  | 12485 | case Builtin::BI__builtin_nansf: | 
|  | 12486 | case Builtin::BI__builtin_nansl: | 
| Benjamin Kramer | dfecbe9 | 2018-01-06 21:49:54 +0000 | [diff] [blame] | 12487 | case Builtin::BI__builtin_nansf128: | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12488 | if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), | 
|  | 12489 | true, Result)) | 
|  | 12490 | return Error(E); | 
|  | 12491 | return true; | 
| John McCall | 1629149 | 2010-02-28 13:00:19 +0000 | [diff] [blame] | 12492 |  | 
| Chris Lattner | 0b7282e | 2008-10-06 06:31:58 +0000 | [diff] [blame] | 12493 | case Builtin::BI__builtin_nan: | 
|  | 12494 | case Builtin::BI__builtin_nanf: | 
|  | 12495 | case Builtin::BI__builtin_nanl: | 
| Benjamin Kramer | dfecbe9 | 2018-01-06 21:49:54 +0000 | [diff] [blame] | 12496 | case Builtin::BI__builtin_nanf128: | 
| Mike Stump | 2346cd2 | 2009-05-30 03:56:50 +0000 | [diff] [blame] | 12497 | // If this is __builtin_nan() turn this into a nan, otherwise we | 
| Chris Lattner | 0b7282e | 2008-10-06 06:31:58 +0000 | [diff] [blame] | 12498 | // can't constant fold it. | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12499 | if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), | 
|  | 12500 | false, Result)) | 
|  | 12501 | return Error(E); | 
|  | 12502 | return true; | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12503 |  | 
|  | 12504 | case Builtin::BI__builtin_fabs: | 
|  | 12505 | case Builtin::BI__builtin_fabsf: | 
|  | 12506 | case Builtin::BI__builtin_fabsl: | 
| Benjamin Kramer | dfecbe9 | 2018-01-06 21:49:54 +0000 | [diff] [blame] | 12507 | case Builtin::BI__builtin_fabsf128: | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12508 | if (!EvaluateFloat(E->getArg(0), Result, Info)) | 
|  | 12509 | return false; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12510 |  | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12511 | if (Result.isNegative()) | 
|  | 12512 | Result.changeSign(); | 
|  | 12513 | return true; | 
|  | 12514 |  | 
| Richard Smith | 8889a3d | 2013-06-13 06:26:32 +0000 | [diff] [blame] | 12515 | // FIXME: Builtin::BI__builtin_powi | 
|  | 12516 | // FIXME: Builtin::BI__builtin_powif | 
|  | 12517 | // FIXME: Builtin::BI__builtin_powil | 
|  | 12518 |  | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12519 | case Builtin::BI__builtin_copysign: | 
|  | 12520 | case Builtin::BI__builtin_copysignf: | 
| Benjamin Kramer | dfecbe9 | 2018-01-06 21:49:54 +0000 | [diff] [blame] | 12521 | case Builtin::BI__builtin_copysignl: | 
|  | 12522 | case Builtin::BI__builtin_copysignf128: { | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12523 | APFloat RHS(0.); | 
|  | 12524 | if (!EvaluateFloat(E->getArg(0), Result, Info) || | 
|  | 12525 | !EvaluateFloat(E->getArg(1), RHS, Info)) | 
|  | 12526 | return false; | 
|  | 12527 | Result.copySign(RHS); | 
|  | 12528 | return true; | 
|  | 12529 | } | 
| Chris Lattner | 4deaa4e | 2008-10-06 05:28:25 +0000 | [diff] [blame] | 12530 | } | 
|  | 12531 | } | 
|  | 12532 |  | 
| John McCall | b1fb0d3 | 2010-05-07 22:08:54 +0000 | [diff] [blame] | 12533 | bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { | 
| Eli Friedman | 9571953 | 2010-08-14 20:52:13 +0000 | [diff] [blame] | 12534 | if (E->getSubExpr()->getType()->isAnyComplexType()) { | 
|  | 12535 | ComplexValue CV; | 
|  | 12536 | if (!EvaluateComplex(E->getSubExpr(), CV, Info)) | 
|  | 12537 | return false; | 
|  | 12538 | Result = CV.FloatReal; | 
|  | 12539 | return true; | 
|  | 12540 | } | 
|  | 12541 |  | 
|  | 12542 | return Visit(E->getSubExpr()); | 
| John McCall | b1fb0d3 | 2010-05-07 22:08:54 +0000 | [diff] [blame] | 12543 | } | 
|  | 12544 |  | 
|  | 12545 | bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { | 
| Eli Friedman | 9571953 | 2010-08-14 20:52:13 +0000 | [diff] [blame] | 12546 | if (E->getSubExpr()->getType()->isAnyComplexType()) { | 
|  | 12547 | ComplexValue CV; | 
|  | 12548 | if (!EvaluateComplex(E->getSubExpr(), CV, Info)) | 
|  | 12549 | return false; | 
|  | 12550 | Result = CV.FloatImag; | 
|  | 12551 | return true; | 
|  | 12552 | } | 
|  | 12553 |  | 
| Richard Smith | 4a67812 | 2011-10-24 18:44:57 +0000 | [diff] [blame] | 12554 | VisitIgnoredValue(E->getSubExpr()); | 
| Eli Friedman | 9571953 | 2010-08-14 20:52:13 +0000 | [diff] [blame] | 12555 | const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); | 
|  | 12556 | Result = llvm::APFloat::getZero(Sem); | 
| John McCall | b1fb0d3 | 2010-05-07 22:08:54 +0000 | [diff] [blame] | 12557 | return true; | 
|  | 12558 | } | 
|  | 12559 |  | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12560 | bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12561 | switch (E->getOpcode()) { | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12562 | default: return Error(E); | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 12563 | case UO_Plus: | 
| Richard Smith | 390cd49 | 2011-10-30 23:17:09 +0000 | [diff] [blame] | 12564 | return EvaluateFloat(E->getSubExpr(), Result, Info); | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 12565 | case UO_Minus: | 
| Richard Smith | 390cd49 | 2011-10-30 23:17:09 +0000 | [diff] [blame] | 12566 | if (!EvaluateFloat(E->getSubExpr(), Result, Info)) | 
|  | 12567 | return false; | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12568 | Result.changeSign(); | 
|  | 12569 | return true; | 
|  | 12570 | } | 
|  | 12571 | } | 
| Chris Lattner | 4deaa4e | 2008-10-06 05:28:25 +0000 | [diff] [blame] | 12572 |  | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12573 | bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 12574 | if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) | 
|  | 12575 | return ExprEvaluatorBaseTy::VisitBinaryOperator(E); | 
| Eli Friedman | 141fbf3 | 2009-11-16 04:25:37 +0000 | [diff] [blame] | 12576 |  | 
| Daniel Dunbar | c3d79cf | 2008-10-16 03:51:50 +0000 | [diff] [blame] | 12577 | APFloat RHS(0.0); | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 12578 | bool LHSOK = EvaluateFloat(E->getLHS(), Result, Info); | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 12579 | if (!LHSOK && !Info.noteFailure()) | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12580 | return false; | 
| Richard Smith | 861b5b5 | 2013-05-07 23:34:45 +0000 | [diff] [blame] | 12581 | return EvaluateFloat(E->getRHS(), RHS, Info) && LHSOK && | 
|  | 12582 | handleFloatFloatBinOp(Info, E, Result, E->getOpcode(), RHS); | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12583 | } | 
|  | 12584 |  | 
|  | 12585 | bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { | 
|  | 12586 | Result = E->getValue(); | 
|  | 12587 | return true; | 
|  | 12588 | } | 
|  | 12589 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12590 | bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { | 
|  | 12591 | const Expr* SubExpr = E->getSubExpr(); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12592 |  | 
| Eli Friedman | 8bfbe3a | 2011-03-25 00:54:52 +0000 | [diff] [blame] | 12593 | switch (E->getCastKind()) { | 
|  | 12594 | default: | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 12595 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
| Eli Friedman | 8bfbe3a | 2011-03-25 00:54:52 +0000 | [diff] [blame] | 12596 |  | 
|  | 12597 | case CK_IntegralToFloating: { | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12598 | APSInt IntResult; | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 12599 | return EvaluateInteger(SubExpr, IntResult, Info) && | 
|  | 12600 | HandleIntToFloatCast(Info, E, SubExpr->getType(), IntResult, | 
|  | 12601 | E->getType(), Result); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12602 | } | 
| Eli Friedman | 8bfbe3a | 2011-03-25 00:54:52 +0000 | [diff] [blame] | 12603 |  | 
|  | 12604 | case CK_FloatingCast: { | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12605 | if (!Visit(SubExpr)) | 
|  | 12606 | return false; | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 12607 | return HandleFloatToFloatCast(Info, E, SubExpr->getType(), E->getType(), | 
|  | 12608 | Result); | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12609 | } | 
| John McCall | d764625 | 2010-11-14 08:17:51 +0000 | [diff] [blame] | 12610 |  | 
| Eli Friedman | 8bfbe3a | 2011-03-25 00:54:52 +0000 | [diff] [blame] | 12611 | case CK_FloatingComplexToReal: { | 
| John McCall | d764625 | 2010-11-14 08:17:51 +0000 | [diff] [blame] | 12612 | ComplexValue V; | 
|  | 12613 | if (!EvaluateComplex(SubExpr, V, Info)) | 
|  | 12614 | return false; | 
|  | 12615 | Result = V.getComplexFloatReal(); | 
|  | 12616 | return true; | 
|  | 12617 | } | 
| Eli Friedman | 8bfbe3a | 2011-03-25 00:54:52 +0000 | [diff] [blame] | 12618 | } | 
| Eli Friedman | 9a156e5 | 2008-11-12 09:44:48 +0000 | [diff] [blame] | 12619 | } | 
|  | 12620 |  | 
| Eli Friedman | 24c0154 | 2008-08-22 00:06:13 +0000 | [diff] [blame] | 12621 | //===----------------------------------------------------------------------===// | 
| Daniel Dunbar | f50e60b | 2009-01-28 22:24:07 +0000 | [diff] [blame] | 12622 | // Complex Evaluation (for float and integer) | 
| Anders Carlsson | 537969c | 2008-11-16 20:27:53 +0000 | [diff] [blame] | 12623 | //===----------------------------------------------------------------------===// | 
|  | 12624 |  | 
|  | 12625 | namespace { | 
| Benjamin Kramer | 26222b6 | 2009-11-28 19:03:38 +0000 | [diff] [blame] | 12626 | class ComplexExprEvaluator | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 12627 | : public ExprEvaluatorBase<ComplexExprEvaluator> { | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12628 | ComplexValue &Result; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12629 |  | 
| Anders Carlsson | 537969c | 2008-11-16 20:27:53 +0000 | [diff] [blame] | 12630 | public: | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12631 | ComplexExprEvaluator(EvalInfo &info, ComplexValue &Result) | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12632 | : ExprEvaluatorBaseTy(info), Result(Result) {} | 
|  | 12633 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 12634 | bool Success(const APValue &V, const Expr *e) { | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12635 | Result.setFrom(V); | 
|  | 12636 | return true; | 
|  | 12637 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12638 |  | 
| Eli Friedman | c4b251d | 2012-01-10 04:58:17 +0000 | [diff] [blame] | 12639 | bool ZeroInitialization(const Expr *E); | 
|  | 12640 |  | 
| Anders Carlsson | 537969c | 2008-11-16 20:27:53 +0000 | [diff] [blame] | 12641 | //===--------------------------------------------------------------------===// | 
|  | 12642 | //                            Visitor Methods | 
|  | 12643 | //===--------------------------------------------------------------------===// | 
|  | 12644 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12645 | bool VisitImaginaryLiteral(const ImaginaryLiteral *E); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12646 | bool VisitCastExpr(const CastExpr *E); | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12647 | bool VisitBinaryOperator(const BinaryOperator *E); | 
| Abramo Bagnara | 9e0e709 | 2010-12-11 16:05:48 +0000 | [diff] [blame] | 12648 | bool VisitUnaryOperator(const UnaryOperator *E); | 
| Eli Friedman | c4b251d | 2012-01-10 04:58:17 +0000 | [diff] [blame] | 12649 | bool VisitInitListExpr(const InitListExpr *E); | 
| Anders Carlsson | 537969c | 2008-11-16 20:27:53 +0000 | [diff] [blame] | 12650 | }; | 
|  | 12651 | } // end anonymous namespace | 
|  | 12652 |  | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12653 | static bool EvaluateComplex(const Expr *E, ComplexValue &Result, | 
|  | 12654 | EvalInfo &Info) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 12655 | assert(E->isRValue() && E->getType()->isAnyComplexType()); | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12656 | return ComplexExprEvaluator(Info, Result).Visit(E); | 
| Anders Carlsson | 537969c | 2008-11-16 20:27:53 +0000 | [diff] [blame] | 12657 | } | 
|  | 12658 |  | 
| Eli Friedman | c4b251d | 2012-01-10 04:58:17 +0000 | [diff] [blame] | 12659 | bool ComplexExprEvaluator::ZeroInitialization(const Expr *E) { | 
| Ted Kremenek | 2883175 | 2012-08-23 20:46:57 +0000 | [diff] [blame] | 12660 | QualType ElemTy = E->getType()->castAs<ComplexType>()->getElementType(); | 
| Eli Friedman | c4b251d | 2012-01-10 04:58:17 +0000 | [diff] [blame] | 12661 | if (ElemTy->isRealFloatingType()) { | 
|  | 12662 | Result.makeComplexFloat(); | 
|  | 12663 | APFloat Zero = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(ElemTy)); | 
|  | 12664 | Result.FloatReal = Zero; | 
|  | 12665 | Result.FloatImag = Zero; | 
|  | 12666 | } else { | 
|  | 12667 | Result.makeComplexInt(); | 
|  | 12668 | APSInt Zero = Info.Ctx.MakeIntValue(0, ElemTy); | 
|  | 12669 | Result.IntReal = Zero; | 
|  | 12670 | Result.IntImag = Zero; | 
|  | 12671 | } | 
|  | 12672 | return true; | 
|  | 12673 | } | 
|  | 12674 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12675 | bool ComplexExprEvaluator::VisitImaginaryLiteral(const ImaginaryLiteral *E) { | 
|  | 12676 | const Expr* SubExpr = E->getSubExpr(); | 
| Eli Friedman | c3e9df3 | 2010-08-16 23:27:44 +0000 | [diff] [blame] | 12677 |  | 
|  | 12678 | if (SubExpr->getType()->isRealFloatingType()) { | 
|  | 12679 | Result.makeComplexFloat(); | 
|  | 12680 | APFloat &Imag = Result.FloatImag; | 
|  | 12681 | if (!EvaluateFloat(SubExpr, Imag, Info)) | 
|  | 12682 | return false; | 
|  | 12683 |  | 
|  | 12684 | Result.FloatReal = APFloat(Imag.getSemantics()); | 
|  | 12685 | return true; | 
|  | 12686 | } else { | 
|  | 12687 | assert(SubExpr->getType()->isIntegerType() && | 
|  | 12688 | "Unexpected imaginary literal."); | 
|  | 12689 |  | 
|  | 12690 | Result.makeComplexInt(); | 
|  | 12691 | APSInt &Imag = Result.IntImag; | 
|  | 12692 | if (!EvaluateInteger(SubExpr, Imag, Info)) | 
|  | 12693 | return false; | 
|  | 12694 |  | 
|  | 12695 | Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned()); | 
|  | 12696 | return true; | 
|  | 12697 | } | 
|  | 12698 | } | 
|  | 12699 |  | 
| Peter Collingbourne | e920068 | 2011-05-13 03:29:01 +0000 | [diff] [blame] | 12700 | bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { | 
| Eli Friedman | c3e9df3 | 2010-08-16 23:27:44 +0000 | [diff] [blame] | 12701 |  | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12702 | switch (E->getCastKind()) { | 
|  | 12703 | case CK_BitCast: | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12704 | case CK_BaseToDerived: | 
|  | 12705 | case CK_DerivedToBase: | 
|  | 12706 | case CK_UncheckedDerivedToBase: | 
|  | 12707 | case CK_Dynamic: | 
|  | 12708 | case CK_ToUnion: | 
|  | 12709 | case CK_ArrayToPointerDecay: | 
|  | 12710 | case CK_FunctionToPointerDecay: | 
|  | 12711 | case CK_NullToPointer: | 
|  | 12712 | case CK_NullToMemberPointer: | 
|  | 12713 | case CK_BaseToDerivedMemberPointer: | 
|  | 12714 | case CK_DerivedToBaseMemberPointer: | 
|  | 12715 | case CK_MemberPointerToBoolean: | 
| John McCall | c62bb39 | 2012-02-15 01:22:51 +0000 | [diff] [blame] | 12716 | case CK_ReinterpretMemberPointer: | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12717 | case CK_ConstructorConversion: | 
|  | 12718 | case CK_IntegralToPointer: | 
|  | 12719 | case CK_PointerToIntegral: | 
|  | 12720 | case CK_PointerToBoolean: | 
|  | 12721 | case CK_ToVoid: | 
|  | 12722 | case CK_VectorSplat: | 
|  | 12723 | case CK_IntegralCast: | 
| George Burgess IV | df1ed00 | 2016-01-13 01:52:39 +0000 | [diff] [blame] | 12724 | case CK_BooleanToSignedIntegral: | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12725 | case CK_IntegralToBoolean: | 
|  | 12726 | case CK_IntegralToFloating: | 
|  | 12727 | case CK_FloatingToIntegral: | 
|  | 12728 | case CK_FloatingToBoolean: | 
|  | 12729 | case CK_FloatingCast: | 
| John McCall | 9320b87 | 2011-09-09 05:25:32 +0000 | [diff] [blame] | 12730 | case CK_CPointerToObjCPointerCast: | 
|  | 12731 | case CK_BlockPointerToObjCPointerCast: | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12732 | case CK_AnyPointerToBlockPointerCast: | 
|  | 12733 | case CK_ObjCObjectLValueCast: | 
|  | 12734 | case CK_FloatingComplexToReal: | 
|  | 12735 | case CK_FloatingComplexToBoolean: | 
|  | 12736 | case CK_IntegralComplexToReal: | 
|  | 12737 | case CK_IntegralComplexToBoolean: | 
| John McCall | 2d637d2 | 2011-09-10 06:18:15 +0000 | [diff] [blame] | 12738 | case CK_ARCProduceObject: | 
|  | 12739 | case CK_ARCConsumeObject: | 
|  | 12740 | case CK_ARCReclaimReturnedObject: | 
|  | 12741 | case CK_ARCExtendBlockObject: | 
| Douglas Gregor | ed90df3 | 2012-02-22 05:02:47 +0000 | [diff] [blame] | 12742 | case CK_CopyAndAutoreleaseBlockObject: | 
| Eli Friedman | 34866c7 | 2012-08-31 00:14:07 +0000 | [diff] [blame] | 12743 | case CK_BuiltinFnToFnPtr: | 
| Andrew Savonichev | b555b76 | 2018-10-23 15:19:20 +0000 | [diff] [blame] | 12744 | case CK_ZeroToOCLOpaqueType: | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 12745 | case CK_NonAtomicToAtomic: | 
| David Tweed | e146832 | 2013-12-11 13:39:46 +0000 | [diff] [blame] | 12746 | case CK_AddressSpaceConversion: | 
| Yaxun Liu | 0bc4b2d | 2016-07-28 19:26:30 +0000 | [diff] [blame] | 12747 | case CK_IntToOCLSampler: | 
| Leonard Chan | 99bda37 | 2018-10-15 16:07:02 +0000 | [diff] [blame] | 12748 | case CK_FixedPointCast: | 
| Leonard Chan | b4ba467 | 2018-10-23 17:55:35 +0000 | [diff] [blame] | 12749 | case CK_FixedPointToBoolean: | 
| Leonard Chan | 8f7caae | 2019-03-06 00:28:43 +0000 | [diff] [blame] | 12750 | case CK_FixedPointToIntegral: | 
|  | 12751 | case CK_IntegralToFixedPoint: | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12752 | llvm_unreachable("invalid cast kind for complex value"); | 
| John McCall | c5e62b4 | 2010-11-13 09:02:35 +0000 | [diff] [blame] | 12753 |  | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12754 | case CK_LValueToRValue: | 
| David Chisnall | fa35df6 | 2012-01-16 17:27:18 +0000 | [diff] [blame] | 12755 | case CK_AtomicToNonAtomic: | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12756 | case CK_NoOp: | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 12757 | case CK_LValueToRValueBitCast: | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 12758 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12759 |  | 
|  | 12760 | case CK_Dependent: | 
| Eli Friedman | c757de2 | 2011-03-25 00:43:55 +0000 | [diff] [blame] | 12761 | case CK_LValueBitCast: | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12762 | case CK_UserDefinedConversion: | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12763 | return Error(E); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12764 |  | 
|  | 12765 | case CK_FloatingRealToComplex: { | 
| Eli Friedman | c3e9df3 | 2010-08-16 23:27:44 +0000 | [diff] [blame] | 12766 | APFloat &Real = Result.FloatReal; | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12767 | if (!EvaluateFloat(E->getSubExpr(), Real, Info)) | 
| Eli Friedman | c3e9df3 | 2010-08-16 23:27:44 +0000 | [diff] [blame] | 12768 | return false; | 
|  | 12769 |  | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12770 | Result.makeComplexFloat(); | 
|  | 12771 | Result.FloatImag = APFloat(Real.getSemantics()); | 
|  | 12772 | return true; | 
| Eli Friedman | c3e9df3 | 2010-08-16 23:27:44 +0000 | [diff] [blame] | 12773 | } | 
|  | 12774 |  | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12775 | case CK_FloatingComplexCast: { | 
|  | 12776 | if (!Visit(E->getSubExpr())) | 
|  | 12777 | return false; | 
|  | 12778 |  | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 12779 | QualType To = E->getType()->castAs<ComplexType>()->getElementType(); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12780 | QualType From | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 12781 | = E->getSubExpr()->getType()->castAs<ComplexType>()->getElementType(); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12782 |  | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 12783 | return HandleFloatToFloatCast(Info, E, From, To, Result.FloatReal) && | 
|  | 12784 | HandleFloatToFloatCast(Info, E, From, To, Result.FloatImag); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12785 | } | 
|  | 12786 |  | 
|  | 12787 | case CK_FloatingComplexToIntegralComplex: { | 
|  | 12788 | if (!Visit(E->getSubExpr())) | 
|  | 12789 | return false; | 
|  | 12790 |  | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 12791 | QualType To = E->getType()->castAs<ComplexType>()->getElementType(); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12792 | QualType From | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 12793 | = E->getSubExpr()->getType()->castAs<ComplexType>()->getElementType(); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12794 | Result.makeComplexInt(); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 12795 | return HandleFloatToIntCast(Info, E, From, Result.FloatReal, | 
|  | 12796 | To, Result.IntReal) && | 
|  | 12797 | HandleFloatToIntCast(Info, E, From, Result.FloatImag, | 
|  | 12798 | To, Result.IntImag); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12799 | } | 
|  | 12800 |  | 
|  | 12801 | case CK_IntegralRealToComplex: { | 
|  | 12802 | APSInt &Real = Result.IntReal; | 
|  | 12803 | if (!EvaluateInteger(E->getSubExpr(), Real, Info)) | 
|  | 12804 | return false; | 
|  | 12805 |  | 
|  | 12806 | Result.makeComplexInt(); | 
|  | 12807 | Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned()); | 
|  | 12808 | return true; | 
|  | 12809 | } | 
|  | 12810 |  | 
|  | 12811 | case CK_IntegralComplexCast: { | 
|  | 12812 | if (!Visit(E->getSubExpr())) | 
|  | 12813 | return false; | 
|  | 12814 |  | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 12815 | QualType To = E->getType()->castAs<ComplexType>()->getElementType(); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12816 | QualType From | 
| Simon Pilgrim | c15b38e | 2019-10-03 15:08:30 +0000 | [diff] [blame] | 12817 | = E->getSubExpr()->getType()->castAs<ComplexType>()->getElementType(); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12818 |  | 
| Richard Smith | 911e142 | 2012-01-30 22:27:01 +0000 | [diff] [blame] | 12819 | Result.IntReal = HandleIntToIntCast(Info, E, To, From, Result.IntReal); | 
|  | 12820 | Result.IntImag = HandleIntToIntCast(Info, E, To, From, Result.IntImag); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12821 | return true; | 
|  | 12822 | } | 
|  | 12823 |  | 
|  | 12824 | case CK_IntegralComplexToFloatingComplex: { | 
|  | 12825 | if (!Visit(E->getSubExpr())) | 
|  | 12826 | return false; | 
|  | 12827 |  | 
| Ted Kremenek | 2883175 | 2012-08-23 20:46:57 +0000 | [diff] [blame] | 12828 | QualType To = E->getType()->castAs<ComplexType>()->getElementType(); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12829 | QualType From | 
| Ted Kremenek | 2883175 | 2012-08-23 20:46:57 +0000 | [diff] [blame] | 12830 | = E->getSubExpr()->getType()->castAs<ComplexType>()->getElementType(); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12831 | Result.makeComplexFloat(); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 12832 | return HandleIntToFloatCast(Info, E, From, Result.IntReal, | 
|  | 12833 | To, Result.FloatReal) && | 
|  | 12834 | HandleIntToFloatCast(Info, E, From, Result.IntImag, | 
|  | 12835 | To, Result.FloatImag); | 
| John McCall | fcef3cf | 2010-12-14 17:51:41 +0000 | [diff] [blame] | 12836 | } | 
|  | 12837 | } | 
|  | 12838 |  | 
|  | 12839 | llvm_unreachable("unknown cast resulting in complex value"); | 
| Eli Friedman | c3e9df3 | 2010-08-16 23:27:44 +0000 | [diff] [blame] | 12840 | } | 
|  | 12841 |  | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12842 | bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 12843 | if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) | 
| Richard Smith | 10f4d06 | 2011-11-16 17:22:48 +0000 | [diff] [blame] | 12844 | return ExprEvaluatorBaseTy::VisitBinaryOperator(E); | 
|  | 12845 |  | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12846 | // Track whether the LHS or RHS is real at the type system level. When this is | 
|  | 12847 | // the case we can simplify our evaluation strategy. | 
|  | 12848 | bool LHSReal = false, RHSReal = false; | 
|  | 12849 |  | 
|  | 12850 | bool LHSOK; | 
|  | 12851 | if (E->getLHS()->getType()->isRealFloatingType()) { | 
|  | 12852 | LHSReal = true; | 
|  | 12853 | APFloat &Real = Result.FloatReal; | 
|  | 12854 | LHSOK = EvaluateFloat(E->getLHS(), Real, Info); | 
|  | 12855 | if (LHSOK) { | 
|  | 12856 | Result.makeComplexFloat(); | 
|  | 12857 | Result.FloatImag = APFloat(Real.getSemantics()); | 
|  | 12858 | } | 
|  | 12859 | } else { | 
|  | 12860 | LHSOK = Visit(E->getLHS()); | 
|  | 12861 | } | 
| George Burgess IV | a145e25 | 2016-05-25 22:38:36 +0000 | [diff] [blame] | 12862 | if (!LHSOK && !Info.noteFailure()) | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12863 | return false; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12864 |  | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12865 | ComplexValue RHS; | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12866 | if (E->getRHS()->getType()->isRealFloatingType()) { | 
|  | 12867 | RHSReal = true; | 
|  | 12868 | APFloat &Real = RHS.FloatReal; | 
|  | 12869 | if (!EvaluateFloat(E->getRHS(), Real, Info) || !LHSOK) | 
|  | 12870 | return false; | 
|  | 12871 | RHS.makeComplexFloat(); | 
|  | 12872 | RHS.FloatImag = APFloat(Real.getSemantics()); | 
|  | 12873 | } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12874 | return false; | 
| Daniel Dunbar | f50e60b | 2009-01-28 22:24:07 +0000 | [diff] [blame] | 12875 |  | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12876 | assert(!(LHSReal && RHSReal) && | 
|  | 12877 | "Cannot have both operands of a complex operation be real."); | 
| Anders Carlsson | 9ddf7be | 2008-11-16 21:51:21 +0000 | [diff] [blame] | 12878 | switch (E->getOpcode()) { | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 12879 | default: return Error(E); | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 12880 | case BO_Add: | 
| Daniel Dunbar | f50e60b | 2009-01-28 22:24:07 +0000 | [diff] [blame] | 12881 | if (Result.isComplexFloat()) { | 
|  | 12882 | Result.getComplexFloatReal().add(RHS.getComplexFloatReal(), | 
|  | 12883 | APFloat::rmNearestTiesToEven); | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12884 | if (LHSReal) | 
|  | 12885 | Result.getComplexFloatImag() = RHS.getComplexFloatImag(); | 
|  | 12886 | else if (!RHSReal) | 
|  | 12887 | Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), | 
|  | 12888 | APFloat::rmNearestTiesToEven); | 
| Daniel Dunbar | f50e60b | 2009-01-28 22:24:07 +0000 | [diff] [blame] | 12889 | } else { | 
|  | 12890 | Result.getComplexIntReal() += RHS.getComplexIntReal(); | 
|  | 12891 | Result.getComplexIntImag() += RHS.getComplexIntImag(); | 
|  | 12892 | } | 
| Daniel Dunbar | 0aa2606 | 2009-01-29 01:32:56 +0000 | [diff] [blame] | 12893 | break; | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 12894 | case BO_Sub: | 
| Daniel Dunbar | f50e60b | 2009-01-28 22:24:07 +0000 | [diff] [blame] | 12895 | if (Result.isComplexFloat()) { | 
|  | 12896 | Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(), | 
|  | 12897 | APFloat::rmNearestTiesToEven); | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12898 | if (LHSReal) { | 
|  | 12899 | Result.getComplexFloatImag() = RHS.getComplexFloatImag(); | 
|  | 12900 | Result.getComplexFloatImag().changeSign(); | 
|  | 12901 | } else if (!RHSReal) { | 
|  | 12902 | Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), | 
|  | 12903 | APFloat::rmNearestTiesToEven); | 
|  | 12904 | } | 
| Daniel Dunbar | f50e60b | 2009-01-28 22:24:07 +0000 | [diff] [blame] | 12905 | } else { | 
|  | 12906 | Result.getComplexIntReal() -= RHS.getComplexIntReal(); | 
|  | 12907 | Result.getComplexIntImag() -= RHS.getComplexIntImag(); | 
|  | 12908 | } | 
| Daniel Dunbar | 0aa2606 | 2009-01-29 01:32:56 +0000 | [diff] [blame] | 12909 | break; | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 12910 | case BO_Mul: | 
| Daniel Dunbar | 0aa2606 | 2009-01-29 01:32:56 +0000 | [diff] [blame] | 12911 | if (Result.isComplexFloat()) { | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12912 | // This is an implementation of complex multiplication according to the | 
| Raphael Isemann | b23ccec | 2018-12-10 12:37:46 +0000 | [diff] [blame] | 12913 | // constraints laid out in C11 Annex G. The implementation uses the | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12914 | // following naming scheme: | 
|  | 12915 | //   (a + ib) * (c + id) | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12916 | ComplexValue LHS = Result; | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12917 | APFloat &A = LHS.getComplexFloatReal(); | 
|  | 12918 | APFloat &B = LHS.getComplexFloatImag(); | 
|  | 12919 | APFloat &C = RHS.getComplexFloatReal(); | 
|  | 12920 | APFloat &D = RHS.getComplexFloatImag(); | 
|  | 12921 | APFloat &ResR = Result.getComplexFloatReal(); | 
|  | 12922 | APFloat &ResI = Result.getComplexFloatImag(); | 
|  | 12923 | if (LHSReal) { | 
|  | 12924 | assert(!RHSReal && "Cannot have two real operands for a complex op!"); | 
|  | 12925 | ResR = A * C; | 
|  | 12926 | ResI = A * D; | 
|  | 12927 | } else if (RHSReal) { | 
|  | 12928 | ResR = C * A; | 
|  | 12929 | ResI = C * B; | 
|  | 12930 | } else { | 
|  | 12931 | // In the fully general case, we need to handle NaNs and infinities | 
|  | 12932 | // robustly. | 
|  | 12933 | APFloat AC = A * C; | 
|  | 12934 | APFloat BD = B * D; | 
|  | 12935 | APFloat AD = A * D; | 
|  | 12936 | APFloat BC = B * C; | 
|  | 12937 | ResR = AC - BD; | 
|  | 12938 | ResI = AD + BC; | 
|  | 12939 | if (ResR.isNaN() && ResI.isNaN()) { | 
|  | 12940 | bool Recalc = false; | 
|  | 12941 | if (A.isInfinity() || B.isInfinity()) { | 
|  | 12942 | A = APFloat::copySign( | 
|  | 12943 | APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); | 
|  | 12944 | B = APFloat::copySign( | 
|  | 12945 | APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); | 
|  | 12946 | if (C.isNaN()) | 
|  | 12947 | C = APFloat::copySign(APFloat(C.getSemantics()), C); | 
|  | 12948 | if (D.isNaN()) | 
|  | 12949 | D = APFloat::copySign(APFloat(D.getSemantics()), D); | 
|  | 12950 | Recalc = true; | 
|  | 12951 | } | 
|  | 12952 | if (C.isInfinity() || D.isInfinity()) { | 
|  | 12953 | C = APFloat::copySign( | 
|  | 12954 | APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); | 
|  | 12955 | D = APFloat::copySign( | 
|  | 12956 | APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); | 
|  | 12957 | if (A.isNaN()) | 
|  | 12958 | A = APFloat::copySign(APFloat(A.getSemantics()), A); | 
|  | 12959 | if (B.isNaN()) | 
|  | 12960 | B = APFloat::copySign(APFloat(B.getSemantics()), B); | 
|  | 12961 | Recalc = true; | 
|  | 12962 | } | 
|  | 12963 | if (!Recalc && (AC.isInfinity() || BD.isInfinity() || | 
|  | 12964 | AD.isInfinity() || BC.isInfinity())) { | 
|  | 12965 | if (A.isNaN()) | 
|  | 12966 | A = APFloat::copySign(APFloat(A.getSemantics()), A); | 
|  | 12967 | if (B.isNaN()) | 
|  | 12968 | B = APFloat::copySign(APFloat(B.getSemantics()), B); | 
|  | 12969 | if (C.isNaN()) | 
|  | 12970 | C = APFloat::copySign(APFloat(C.getSemantics()), C); | 
|  | 12971 | if (D.isNaN()) | 
|  | 12972 | D = APFloat::copySign(APFloat(D.getSemantics()), D); | 
|  | 12973 | Recalc = true; | 
|  | 12974 | } | 
|  | 12975 | if (Recalc) { | 
|  | 12976 | ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D); | 
|  | 12977 | ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C); | 
|  | 12978 | } | 
|  | 12979 | } | 
|  | 12980 | } | 
| Daniel Dunbar | 0aa2606 | 2009-01-29 01:32:56 +0000 | [diff] [blame] | 12981 | } else { | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 12982 | ComplexValue LHS = Result; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12983 | Result.getComplexIntReal() = | 
| Daniel Dunbar | 0aa2606 | 2009-01-29 01:32:56 +0000 | [diff] [blame] | 12984 | (LHS.getComplexIntReal() * RHS.getComplexIntReal() - | 
|  | 12985 | LHS.getComplexIntImag() * RHS.getComplexIntImag()); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 12986 | Result.getComplexIntImag() = | 
| Daniel Dunbar | 0aa2606 | 2009-01-29 01:32:56 +0000 | [diff] [blame] | 12987 | (LHS.getComplexIntReal() * RHS.getComplexIntImag() + | 
|  | 12988 | LHS.getComplexIntImag() * RHS.getComplexIntReal()); | 
|  | 12989 | } | 
|  | 12990 | break; | 
| Abramo Bagnara | 9e0e709 | 2010-12-11 16:05:48 +0000 | [diff] [blame] | 12991 | case BO_Div: | 
|  | 12992 | if (Result.isComplexFloat()) { | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12993 | // This is an implementation of complex division according to the | 
| Raphael Isemann | b23ccec | 2018-12-10 12:37:46 +0000 | [diff] [blame] | 12994 | // constraints laid out in C11 Annex G. The implementation uses the | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12995 | // following naming scheme: | 
|  | 12996 | //   (a + ib) / (c + id) | 
| Abramo Bagnara | 9e0e709 | 2010-12-11 16:05:48 +0000 | [diff] [blame] | 12997 | ComplexValue LHS = Result; | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 12998 | APFloat &A = LHS.getComplexFloatReal(); | 
|  | 12999 | APFloat &B = LHS.getComplexFloatImag(); | 
|  | 13000 | APFloat &C = RHS.getComplexFloatReal(); | 
|  | 13001 | APFloat &D = RHS.getComplexFloatImag(); | 
|  | 13002 | APFloat &ResR = Result.getComplexFloatReal(); | 
|  | 13003 | APFloat &ResI = Result.getComplexFloatImag(); | 
|  | 13004 | if (RHSReal) { | 
|  | 13005 | ResR = A / C; | 
|  | 13006 | ResI = B / C; | 
|  | 13007 | } else { | 
|  | 13008 | if (LHSReal) { | 
|  | 13009 | // No real optimizations we can do here, stub out with zero. | 
|  | 13010 | B = APFloat::getZero(A.getSemantics()); | 
|  | 13011 | } | 
|  | 13012 | int DenomLogB = 0; | 
|  | 13013 | APFloat MaxCD = maxnum(abs(C), abs(D)); | 
|  | 13014 | if (MaxCD.isFinite()) { | 
|  | 13015 | DenomLogB = ilogb(MaxCD); | 
| Matt Arsenault | c477f48 | 2016-03-13 05:12:47 +0000 | [diff] [blame] | 13016 | C = scalbn(C, -DenomLogB, APFloat::rmNearestTiesToEven); | 
|  | 13017 | D = scalbn(D, -DenomLogB, APFloat::rmNearestTiesToEven); | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 13018 | } | 
|  | 13019 | APFloat Denom = C * C + D * D; | 
| Matt Arsenault | c477f48 | 2016-03-13 05:12:47 +0000 | [diff] [blame] | 13020 | ResR = scalbn((A * C + B * D) / Denom, -DenomLogB, | 
|  | 13021 | APFloat::rmNearestTiesToEven); | 
|  | 13022 | ResI = scalbn((B * C - A * D) / Denom, -DenomLogB, | 
|  | 13023 | APFloat::rmNearestTiesToEven); | 
| Chandler Carruth | a216cad | 2014-10-11 00:57:18 +0000 | [diff] [blame] | 13024 | if (ResR.isNaN() && ResI.isNaN()) { | 
|  | 13025 | if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) { | 
|  | 13026 | ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A; | 
|  | 13027 | ResI = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * B; | 
|  | 13028 | } else if ((A.isInfinity() || B.isInfinity()) && C.isFinite() && | 
|  | 13029 | D.isFinite()) { | 
|  | 13030 | A = APFloat::copySign( | 
|  | 13031 | APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); | 
|  | 13032 | B = APFloat::copySign( | 
|  | 13033 | APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); | 
|  | 13034 | ResR = APFloat::getInf(ResR.getSemantics()) * (A * C + B * D); | 
|  | 13035 | ResI = APFloat::getInf(ResI.getSemantics()) * (B * C - A * D); | 
|  | 13036 | } else if (MaxCD.isInfinity() && A.isFinite() && B.isFinite()) { | 
|  | 13037 | C = APFloat::copySign( | 
|  | 13038 | APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); | 
|  | 13039 | D = APFloat::copySign( | 
|  | 13040 | APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); | 
|  | 13041 | ResR = APFloat::getZero(ResR.getSemantics()) * (A * C + B * D); | 
|  | 13042 | ResI = APFloat::getZero(ResI.getSemantics()) * (B * C - A * D); | 
|  | 13043 | } | 
|  | 13044 | } | 
|  | 13045 | } | 
| Abramo Bagnara | 9e0e709 | 2010-12-11 16:05:48 +0000 | [diff] [blame] | 13046 | } else { | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 13047 | if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) | 
|  | 13048 | return Error(E, diag::note_expr_divide_by_zero); | 
|  | 13049 |  | 
| Abramo Bagnara | 9e0e709 | 2010-12-11 16:05:48 +0000 | [diff] [blame] | 13050 | ComplexValue LHS = Result; | 
|  | 13051 | APSInt Den = RHS.getComplexIntReal() * RHS.getComplexIntReal() + | 
|  | 13052 | RHS.getComplexIntImag() * RHS.getComplexIntImag(); | 
|  | 13053 | Result.getComplexIntReal() = | 
|  | 13054 | (LHS.getComplexIntReal() * RHS.getComplexIntReal() + | 
|  | 13055 | LHS.getComplexIntImag() * RHS.getComplexIntImag()) / Den; | 
|  | 13056 | Result.getComplexIntImag() = | 
|  | 13057 | (LHS.getComplexIntImag() * RHS.getComplexIntReal() - | 
|  | 13058 | LHS.getComplexIntReal() * RHS.getComplexIntImag()) / Den; | 
|  | 13059 | } | 
|  | 13060 | break; | 
| Anders Carlsson | 9ddf7be | 2008-11-16 21:51:21 +0000 | [diff] [blame] | 13061 | } | 
|  | 13062 |  | 
| John McCall | 93d91dc | 2010-05-07 17:22:02 +0000 | [diff] [blame] | 13063 | return true; | 
| Anders Carlsson | 9ddf7be | 2008-11-16 21:51:21 +0000 | [diff] [blame] | 13064 | } | 
|  | 13065 |  | 
| Abramo Bagnara | 9e0e709 | 2010-12-11 16:05:48 +0000 | [diff] [blame] | 13066 | bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { | 
|  | 13067 | // Get the operand value into 'Result'. | 
|  | 13068 | if (!Visit(E->getSubExpr())) | 
|  | 13069 | return false; | 
|  | 13070 |  | 
|  | 13071 | switch (E->getOpcode()) { | 
|  | 13072 | default: | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 13073 | return Error(E); | 
| Abramo Bagnara | 9e0e709 | 2010-12-11 16:05:48 +0000 | [diff] [blame] | 13074 | case UO_Extension: | 
|  | 13075 | return true; | 
|  | 13076 | case UO_Plus: | 
|  | 13077 | // The result is always just the subexpr. | 
|  | 13078 | return true; | 
|  | 13079 | case UO_Minus: | 
|  | 13080 | if (Result.isComplexFloat()) { | 
|  | 13081 | Result.getComplexFloatReal().changeSign(); | 
|  | 13082 | Result.getComplexFloatImag().changeSign(); | 
|  | 13083 | } | 
|  | 13084 | else { | 
|  | 13085 | Result.getComplexIntReal() = -Result.getComplexIntReal(); | 
|  | 13086 | Result.getComplexIntImag() = -Result.getComplexIntImag(); | 
|  | 13087 | } | 
|  | 13088 | return true; | 
|  | 13089 | case UO_Not: | 
|  | 13090 | if (Result.isComplexFloat()) | 
|  | 13091 | Result.getComplexFloatImag().changeSign(); | 
|  | 13092 | else | 
|  | 13093 | Result.getComplexIntImag() = -Result.getComplexIntImag(); | 
|  | 13094 | return true; | 
|  | 13095 | } | 
|  | 13096 | } | 
|  | 13097 |  | 
| Eli Friedman | c4b251d | 2012-01-10 04:58:17 +0000 | [diff] [blame] | 13098 | bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) { | 
|  | 13099 | if (E->getNumInits() == 2) { | 
|  | 13100 | if (E->getType()->isComplexType()) { | 
|  | 13101 | Result.makeComplexFloat(); | 
|  | 13102 | if (!EvaluateFloat(E->getInit(0), Result.FloatReal, Info)) | 
|  | 13103 | return false; | 
|  | 13104 | if (!EvaluateFloat(E->getInit(1), Result.FloatImag, Info)) | 
|  | 13105 | return false; | 
|  | 13106 | } else { | 
|  | 13107 | Result.makeComplexInt(); | 
|  | 13108 | if (!EvaluateInteger(E->getInit(0), Result.IntReal, Info)) | 
|  | 13109 | return false; | 
|  | 13110 | if (!EvaluateInteger(E->getInit(1), Result.IntImag, Info)) | 
|  | 13111 | return false; | 
|  | 13112 | } | 
|  | 13113 | return true; | 
|  | 13114 | } | 
|  | 13115 | return ExprEvaluatorBaseTy::VisitInitListExpr(E); | 
|  | 13116 | } | 
|  | 13117 |  | 
| Anders Carlsson | 537969c | 2008-11-16 20:27:53 +0000 | [diff] [blame] | 13118 | //===----------------------------------------------------------------------===// | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13119 | // Atomic expression evaluation, essentially just handling the NonAtomicToAtomic | 
|  | 13120 | // implicit conversion. | 
|  | 13121 | //===----------------------------------------------------------------------===// | 
|  | 13122 |  | 
|  | 13123 | namespace { | 
|  | 13124 | class AtomicExprEvaluator : | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 13125 | public ExprEvaluatorBase<AtomicExprEvaluator> { | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13126 | const LValue *This; | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13127 | APValue &Result; | 
|  | 13128 | public: | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13129 | AtomicExprEvaluator(EvalInfo &Info, const LValue *This, APValue &Result) | 
|  | 13130 | : ExprEvaluatorBaseTy(Info), This(This), Result(Result) {} | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13131 |  | 
|  | 13132 | bool Success(const APValue &V, const Expr *E) { | 
|  | 13133 | Result = V; | 
|  | 13134 | return true; | 
|  | 13135 | } | 
|  | 13136 |  | 
|  | 13137 | bool ZeroInitialization(const Expr *E) { | 
|  | 13138 | ImplicitValueInitExpr VIE( | 
|  | 13139 | E->getType()->castAs<AtomicType>()->getValueType()); | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13140 | // For atomic-qualified class (and array) types in C++, initialize the | 
|  | 13141 | // _Atomic-wrapped subobject directly, in-place. | 
|  | 13142 | return This ? EvaluateInPlace(Result, Info, *This, &VIE) | 
|  | 13143 | : Evaluate(Result, Info, &VIE); | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13144 | } | 
|  | 13145 |  | 
|  | 13146 | bool VisitCastExpr(const CastExpr *E) { | 
|  | 13147 | switch (E->getCastKind()) { | 
|  | 13148 | default: | 
|  | 13149 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
|  | 13150 | case CK_NonAtomicToAtomic: | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13151 | return This ? EvaluateInPlace(Result, Info, *This, E->getSubExpr()) | 
|  | 13152 | : Evaluate(Result, Info, E->getSubExpr()); | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13153 | } | 
|  | 13154 | } | 
|  | 13155 | }; | 
|  | 13156 | } // end anonymous namespace | 
|  | 13157 |  | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13158 | static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result, | 
|  | 13159 | EvalInfo &Info) { | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13160 | assert(E->isRValue() && E->getType()->isAtomicType()); | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13161 | return AtomicExprEvaluator(Info, This, Result).Visit(E); | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13162 | } | 
|  | 13163 |  | 
|  | 13164 | //===----------------------------------------------------------------------===// | 
| Richard Smith | 42d3af9 | 2011-12-07 00:43:50 +0000 | [diff] [blame] | 13165 | // Void expression evaluation, primarily for a cast to void on the LHS of a | 
|  | 13166 | // comma operator | 
|  | 13167 | //===----------------------------------------------------------------------===// | 
|  | 13168 |  | 
|  | 13169 | namespace { | 
|  | 13170 | class VoidExprEvaluator | 
| Aaron Ballman | 68af21c | 2014-01-03 19:26:43 +0000 | [diff] [blame] | 13171 | : public ExprEvaluatorBase<VoidExprEvaluator> { | 
| Richard Smith | 42d3af9 | 2011-12-07 00:43:50 +0000 | [diff] [blame] | 13172 | public: | 
|  | 13173 | VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {} | 
|  | 13174 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 13175 | bool Success(const APValue &V, const Expr *e) { return true; } | 
| Richard Smith | 42d3af9 | 2011-12-07 00:43:50 +0000 | [diff] [blame] | 13176 |  | 
| Richard Smith | 7cd577b | 2017-08-17 19:35:50 +0000 | [diff] [blame] | 13177 | bool ZeroInitialization(const Expr *E) { return true; } | 
|  | 13178 |  | 
| Richard Smith | 42d3af9 | 2011-12-07 00:43:50 +0000 | [diff] [blame] | 13179 | bool VisitCastExpr(const CastExpr *E) { | 
|  | 13180 | switch (E->getCastKind()) { | 
|  | 13181 | default: | 
|  | 13182 | return ExprEvaluatorBaseTy::VisitCastExpr(E); | 
|  | 13183 | case CK_ToVoid: | 
|  | 13184 | VisitIgnoredValue(E->getSubExpr()); | 
|  | 13185 | return true; | 
|  | 13186 | } | 
|  | 13187 | } | 
| Hal Finkel | a8443c3 | 2014-07-17 14:49:58 +0000 | [diff] [blame] | 13188 |  | 
|  | 13189 | bool VisitCallExpr(const CallExpr *E) { | 
|  | 13190 | switch (E->getBuiltinCallee()) { | 
| Hal Finkel | a8443c3 | 2014-07-17 14:49:58 +0000 | [diff] [blame] | 13191 | case Builtin::BI__assume: | 
| Hal Finkel | bcc0608 | 2014-09-07 22:58:14 +0000 | [diff] [blame] | 13192 | case Builtin::BI__builtin_assume: | 
| Hal Finkel | a8443c3 | 2014-07-17 14:49:58 +0000 | [diff] [blame] | 13193 | // The argument is not evaluated! | 
|  | 13194 | return true; | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 13195 |  | 
|  | 13196 | case Builtin::BI__builtin_operator_delete: | 
|  | 13197 | return HandleOperatorDeleteCall(Info, E); | 
|  | 13198 |  | 
|  | 13199 | default: | 
|  | 13200 | break; | 
| Hal Finkel | a8443c3 | 2014-07-17 14:49:58 +0000 | [diff] [blame] | 13201 | } | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 13202 |  | 
|  | 13203 | return ExprEvaluatorBaseTy::VisitCallExpr(E); | 
| Hal Finkel | a8443c3 | 2014-07-17 14:49:58 +0000 | [diff] [blame] | 13204 | } | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13205 |  | 
|  | 13206 | bool VisitCXXDeleteExpr(const CXXDeleteExpr *E); | 
| Richard Smith | 42d3af9 | 2011-12-07 00:43:50 +0000 | [diff] [blame] | 13207 | }; | 
|  | 13208 | } // end anonymous namespace | 
|  | 13209 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13210 | bool VoidExprEvaluator::VisitCXXDeleteExpr(const CXXDeleteExpr *E) { | 
|  | 13211 | // We cannot speculatively evaluate a delete expression. | 
|  | 13212 | if (Info.SpeculativeEvaluationDepth) | 
|  | 13213 | return false; | 
|  | 13214 |  | 
|  | 13215 | FunctionDecl *OperatorDelete = E->getOperatorDelete(); | 
|  | 13216 | if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) { | 
|  | 13217 | Info.FFDiag(E, diag::note_constexpr_new_non_replaceable) | 
|  | 13218 | << isa<CXXMethodDecl>(OperatorDelete) << OperatorDelete; | 
|  | 13219 | return false; | 
|  | 13220 | } | 
|  | 13221 |  | 
|  | 13222 | const Expr *Arg = E->getArgument(); | 
|  | 13223 |  | 
|  | 13224 | LValue Pointer; | 
|  | 13225 | if (!EvaluatePointer(Arg, Pointer, Info)) | 
|  | 13226 | return false; | 
|  | 13227 | if (Pointer.Designator.Invalid) | 
|  | 13228 | return false; | 
|  | 13229 |  | 
|  | 13230 | // Deleting a null pointer has no effect. | 
|  | 13231 | if (Pointer.isNullPointer()) { | 
|  | 13232 | // This is the only case where we need to produce an extension warning: | 
|  | 13233 | // the only other way we can succeed is if we find a dynamic allocation, | 
|  | 13234 | // and we will have warned when we allocated it in that case. | 
|  | 13235 | if (!Info.getLangOpts().CPlusPlus2a) | 
|  | 13236 | Info.CCEDiag(E, diag::note_constexpr_new); | 
|  | 13237 | return true; | 
|  | 13238 | } | 
|  | 13239 |  | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 13240 | Optional<DynAlloc *> Alloc = CheckDeleteKind( | 
|  | 13241 | Info, E, Pointer, E->isArrayForm() ? DynAlloc::ArrayNew : DynAlloc::New); | 
|  | 13242 | if (!Alloc) | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13243 | return false; | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13244 | QualType AllocType = Pointer.Base.getDynamicAllocType(); | 
|  | 13245 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13246 | // For the non-array case, the designator must be empty if the static type | 
|  | 13247 | // does not have a virtual destructor. | 
|  | 13248 | if (!E->isArrayForm() && Pointer.Designator.Entries.size() != 0 && | 
|  | 13249 | !hasVirtualDestructor(Arg->getType()->getPointeeType())) { | 
|  | 13250 | Info.FFDiag(E, diag::note_constexpr_delete_base_nonvirt_dtor) | 
|  | 13251 | << Arg->getType()->getPointeeType() << AllocType; | 
|  | 13252 | return false; | 
|  | 13253 | } | 
|  | 13254 |  | 
| Richard Smith | df3761f | 2019-10-07 03:14:28 +0000 | [diff] [blame] | 13255 | // For a class type with a virtual destructor, the selected operator delete | 
|  | 13256 | // is the one looked up when building the destructor. | 
|  | 13257 | if (!E->isArrayForm() && !E->isGlobalDelete()) { | 
|  | 13258 | const FunctionDecl *VirtualDelete = getVirtualOperatorDelete(AllocType); | 
|  | 13259 | if (VirtualDelete && | 
|  | 13260 | !VirtualDelete->isReplaceableGlobalAllocationFunction()) { | 
|  | 13261 | Info.FFDiag(E, diag::note_constexpr_new_non_replaceable) | 
|  | 13262 | << isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete; | 
|  | 13263 | return false; | 
|  | 13264 | } | 
|  | 13265 | } | 
|  | 13266 |  | 
| Richard Smith | 61422f9 | 2019-09-27 20:24:36 +0000 | [diff] [blame] | 13267 | if (!HandleDestruction(Info, E->getExprLoc(), Pointer.getLValueBase(), | 
|  | 13268 | (*Alloc)->Value, AllocType)) | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13269 | return false; | 
|  | 13270 |  | 
| Richard Smith | 19ad523 | 2019-10-03 00:39:33 +0000 | [diff] [blame] | 13271 | if (!Info.HeapAllocs.erase(Pointer.Base.dyn_cast<DynamicAllocLValue>())) { | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13272 | // The element was already erased. This means the destructor call also | 
|  | 13273 | // deleted the object. | 
|  | 13274 | // FIXME: This probably results in undefined behavior before we get this | 
|  | 13275 | // far, and should be diagnosed elsewhere first. | 
|  | 13276 | Info.FFDiag(E, diag::note_constexpr_double_delete); | 
|  | 13277 | return false; | 
|  | 13278 | } | 
|  | 13279 |  | 
|  | 13280 | return true; | 
|  | 13281 | } | 
|  | 13282 |  | 
| Richard Smith | 42d3af9 | 2011-12-07 00:43:50 +0000 | [diff] [blame] | 13283 | static bool EvaluateVoid(const Expr *E, EvalInfo &Info) { | 
|  | 13284 | assert(E->isRValue() && E->getType()->isVoidType()); | 
|  | 13285 | return VoidExprEvaluator(Info).Visit(E); | 
|  | 13286 | } | 
|  | 13287 |  | 
|  | 13288 | //===----------------------------------------------------------------------===// | 
| Richard Smith | 7b553f1 | 2011-10-29 00:50:52 +0000 | [diff] [blame] | 13289 | // Top level Expr::EvaluateAsRValue method. | 
| Chris Lattner | 05706e88 | 2008-07-11 18:11:29 +0000 | [diff] [blame] | 13290 | //===----------------------------------------------------------------------===// | 
|  | 13291 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 13292 | static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 13293 | // In C, function designators are not lvalues, but we evaluate them as if they | 
|  | 13294 | // are. | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13295 | QualType T = E->getType(); | 
|  | 13296 | if (E->isGLValue() || T->isFunctionType()) { | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 13297 | LValue LV; | 
|  | 13298 | if (!EvaluateLValue(E, LV, Info)) | 
|  | 13299 | return false; | 
|  | 13300 | LV.moveInto(Result); | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13301 | } else if (T->isVectorType()) { | 
| Richard Smith | 725810a | 2011-10-16 21:26:27 +0000 | [diff] [blame] | 13302 | if (!EvaluateVector(E, Result, Info)) | 
| Nate Begeman | 2f2bdeb | 2009-01-18 03:20:47 +0000 | [diff] [blame] | 13303 | return false; | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13304 | } else if (T->isIntegralOrEnumerationType()) { | 
| Richard Smith | 725810a | 2011-10-16 21:26:27 +0000 | [diff] [blame] | 13305 | if (!IntExprEvaluator(Info, Result).Visit(E)) | 
| Anders Carlsson | 475f4bc | 2008-11-22 21:50:49 +0000 | [diff] [blame] | 13306 | return false; | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13307 | } else if (T->hasPointerRepresentation()) { | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 13308 | LValue LV; | 
|  | 13309 | if (!EvaluatePointer(E, LV, Info)) | 
| Anders Carlsson | 475f4bc | 2008-11-22 21:50:49 +0000 | [diff] [blame] | 13310 | return false; | 
| Richard Smith | 725810a | 2011-10-16 21:26:27 +0000 | [diff] [blame] | 13311 | LV.moveInto(Result); | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13312 | } else if (T->isRealFloatingType()) { | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 13313 | llvm::APFloat F(0.0); | 
|  | 13314 | if (!EvaluateFloat(E, F, Info)) | 
| Anders Carlsson | 475f4bc | 2008-11-22 21:50:49 +0000 | [diff] [blame] | 13315 | return false; | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 13316 | Result = APValue(F); | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13317 | } else if (T->isAnyComplexType()) { | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 13318 | ComplexValue C; | 
|  | 13319 | if (!EvaluateComplex(E, C, Info)) | 
| Anders Carlsson | 475f4bc | 2008-11-22 21:50:49 +0000 | [diff] [blame] | 13320 | return false; | 
| Richard Smith | 725810a | 2011-10-16 21:26:27 +0000 | [diff] [blame] | 13321 | C.moveInto(Result); | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 13322 | } else if (T->isFixedPointType()) { | 
|  | 13323 | if (!FixedPointExprEvaluator(Info, Result).Visit(E)) return false; | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13324 | } else if (T->isMemberPointerType()) { | 
| Richard Smith | 027bf11 | 2011-11-17 22:56:20 +0000 | [diff] [blame] | 13325 | MemberPtr P; | 
|  | 13326 | if (!EvaluateMemberPointer(E, P, Info)) | 
|  | 13327 | return false; | 
|  | 13328 | P.moveInto(Result); | 
|  | 13329 | return true; | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13330 | } else if (T->isArrayType()) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 13331 | LValue LV; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 13332 | APValue &Value = | 
|  | 13333 | Info.CurrentCall->createTemporary(E, T, false, LV); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 13334 | if (!EvaluateArray(E, LV, Value, Info)) | 
| Richard Smith | f3e9e43 | 2011-11-07 09:22:26 +0000 | [diff] [blame] | 13335 | return false; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 13336 | Result = Value; | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13337 | } else if (T->isRecordType()) { | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 13338 | LValue LV; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 13339 | APValue &Value = Info.CurrentCall->createTemporary(E, T, false, LV); | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 13340 | if (!EvaluateRecord(E, LV, Value, Info)) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 13341 | return false; | 
| Richard Smith | 08d6a2c | 2013-07-24 07:11:57 +0000 | [diff] [blame] | 13342 | Result = Value; | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13343 | } else if (T->isVoidType()) { | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 13344 | if (!Info.getLangOpts().CPlusPlus11) | 
| Richard Smith | ce1ec5e | 2012-03-15 04:53:45 +0000 | [diff] [blame] | 13345 | Info.CCEDiag(E, diag::note_constexpr_nonliteral) | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 13346 | << E->getType(); | 
| Richard Smith | 42d3af9 | 2011-12-07 00:43:50 +0000 | [diff] [blame] | 13347 | if (!EvaluateVoid(E, Info)) | 
|  | 13348 | return false; | 
| Richard Smith | a23ab51 | 2013-05-23 00:30:41 +0000 | [diff] [blame] | 13349 | } else if (T->isAtomicType()) { | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13350 | QualType Unqual = T.getAtomicUnqualifiedType(); | 
|  | 13351 | if (Unqual->isArrayType() || Unqual->isRecordType()) { | 
|  | 13352 | LValue LV; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 13353 | APValue &Value = Info.CurrentCall->createTemporary(E, Unqual, false, LV); | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13354 | if (!EvaluateAtomic(E, &LV, Value, Info)) | 
|  | 13355 | return false; | 
|  | 13356 | } else { | 
|  | 13357 | if (!EvaluateAtomic(E, nullptr, Result, Info)) | 
|  | 13358 | return false; | 
|  | 13359 | } | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 13360 | } else if (Info.getLangOpts().CPlusPlus11) { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 13361 | Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType(); | 
| Richard Smith | 357362d | 2011-12-13 06:39:58 +0000 | [diff] [blame] | 13362 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 13363 | } else { | 
| Faisal Vali | e690b7a | 2016-07-02 22:34:24 +0000 | [diff] [blame] | 13364 | Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); | 
| Anders Carlsson | 7c282e4 | 2008-11-22 22:56:32 +0000 | [diff] [blame] | 13365 | return false; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 13366 | } | 
| Anders Carlsson | 475f4bc | 2008-11-22 21:50:49 +0000 | [diff] [blame] | 13367 |  | 
| Anders Carlsson | 7b6f0af | 2008-11-30 16:58:53 +0000 | [diff] [blame] | 13368 | return true; | 
|  | 13369 | } | 
|  | 13370 |  | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 13371 | /// EvaluateInPlace - Evaluate an expression in-place in an APValue. In some | 
|  | 13372 | /// cases, the in-place evaluation is essential, since later initializers for | 
|  | 13373 | /// an object can indirectly refer to subobjects which were initialized earlier. | 
|  | 13374 | static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 13375 | const Expr *E, bool AllowNonLiteralTypes) { | 
| Argyrios Kyrtzidis | 3d9e382 | 2014-02-20 04:00:01 +0000 | [diff] [blame] | 13376 | assert(!E->isValueDependent()); | 
|  | 13377 |  | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 13378 | if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This)) | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 13379 | return false; | 
|  | 13380 |  | 
|  | 13381 | if (E->isRValue()) { | 
| Richard Smith | ed5165f | 2011-11-04 05:33:44 +0000 | [diff] [blame] | 13382 | // Evaluate arrays and record types in-place, so that later initializers can | 
|  | 13383 | // refer to earlier-initialized members of the object. | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13384 | QualType T = E->getType(); | 
|  | 13385 | if (T->isArrayType()) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 13386 | return EvaluateArray(E, This, Result, Info); | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13387 | else if (T->isRecordType()) | 
| Richard Smith | d62306a | 2011-11-10 06:34:14 +0000 | [diff] [blame] | 13388 | return EvaluateRecord(E, This, Result, Info); | 
| Richard Smith | 64cb9ca | 2017-02-22 22:09:50 +0000 | [diff] [blame] | 13389 | else if (T->isAtomicType()) { | 
|  | 13390 | QualType Unqual = T.getAtomicUnqualifiedType(); | 
|  | 13391 | if (Unqual->isArrayType() || Unqual->isRecordType()) | 
|  | 13392 | return EvaluateAtomic(E, &This, Result, Info); | 
|  | 13393 | } | 
| Richard Smith | ed5165f | 2011-11-04 05:33:44 +0000 | [diff] [blame] | 13394 | } | 
|  | 13395 |  | 
|  | 13396 | // For any other type, in-place evaluation is unimportant. | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 13397 | return Evaluate(Result, Info, E); | 
| Richard Smith | ed5165f | 2011-11-04 05:33:44 +0000 | [diff] [blame] | 13398 | } | 
|  | 13399 |  | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 13400 | /// EvaluateAsRValue - Try to evaluate this expression, performing an implicit | 
|  | 13401 | /// lvalue-to-rvalue cast if it is an lvalue. | 
|  | 13402 | static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 13403 | if (Info.EnableNewConstInterp) { | 
|  | 13404 | if (!Info.Ctx.getInterpContext().evaluateAsRValue(Info, E, Result)) | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 13405 | return false; | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 13406 | } else { | 
|  | 13407 | if (E->getType().isNull()) | 
|  | 13408 | return false; | 
|  | 13409 |  | 
|  | 13410 | if (!CheckLiteralType(Info, E)) | 
|  | 13411 | return false; | 
|  | 13412 |  | 
|  | 13413 | if (!::Evaluate(Result, Info, E)) | 
|  | 13414 | return false; | 
|  | 13415 |  | 
|  | 13416 | if (E->isGLValue()) { | 
|  | 13417 | LValue LV; | 
|  | 13418 | LV.setFrom(Info.Ctx, Result); | 
|  | 13419 | if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) | 
|  | 13420 | return false; | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 13421 | } | 
|  | 13422 | } | 
|  | 13423 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 13424 | // Check this core constant expression is a constant expression. | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13425 | return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result) && | 
|  | 13426 | CheckMemoryLeaks(Info); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 13427 | } | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 13428 |  | 
| Fariborz Jahanian | e735ff9 | 2013-01-24 22:11:45 +0000 | [diff] [blame] | 13429 | static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, | 
| Richard Smith | 9f7df0c | 2017-06-26 23:19:32 +0000 | [diff] [blame] | 13430 | const ASTContext &Ctx, bool &IsConst) { | 
| Fariborz Jahanian | e735ff9 | 2013-01-24 22:11:45 +0000 | [diff] [blame] | 13431 | // Fast-path evaluations of integer literals, since we sometimes see files | 
|  | 13432 | // containing vast quantities of these. | 
|  | 13433 | if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(Exp)) { | 
|  | 13434 | Result.Val = APValue(APSInt(L->getValue(), | 
|  | 13435 | L->getType()->isUnsignedIntegerType())); | 
|  | 13436 | IsConst = true; | 
|  | 13437 | return true; | 
|  | 13438 | } | 
| James Dennett | 0492ef0 | 2014-03-14 17:44:10 +0000 | [diff] [blame] | 13439 |  | 
|  | 13440 | // This case should be rare, but we need to check it before we check on | 
|  | 13441 | // the type below. | 
|  | 13442 | if (Exp->getType().isNull()) { | 
|  | 13443 | IsConst = false; | 
|  | 13444 | return true; | 
|  | 13445 | } | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 13446 |  | 
| Fariborz Jahanian | e735ff9 | 2013-01-24 22:11:45 +0000 | [diff] [blame] | 13447 | // FIXME: Evaluating values of large array and record types can cause | 
|  | 13448 | // performance problems. Only do so in C++11 for now. | 
|  | 13449 | if (Exp->isRValue() && (Exp->getType()->isArrayType() || | 
|  | 13450 | Exp->getType()->isRecordType()) && | 
| Richard Smith | 9f7df0c | 2017-06-26 23:19:32 +0000 | [diff] [blame] | 13451 | !Ctx.getLangOpts().CPlusPlus11) { | 
| Fariborz Jahanian | e735ff9 | 2013-01-24 22:11:45 +0000 | [diff] [blame] | 13452 | IsConst = false; | 
|  | 13453 | return true; | 
|  | 13454 | } | 
|  | 13455 | return false; | 
|  | 13456 | } | 
|  | 13457 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13458 | static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, | 
|  | 13459 | Expr::SideEffectsKind SEK) { | 
|  | 13460 | return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) || | 
|  | 13461 | (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior); | 
|  | 13462 | } | 
|  | 13463 |  | 
|  | 13464 | static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result, | 
|  | 13465 | const ASTContext &Ctx, EvalInfo &Info) { | 
|  | 13466 | bool IsConst; | 
|  | 13467 | if (FastEvaluateAsRValue(E, Result, Ctx, IsConst)) | 
|  | 13468 | return IsConst; | 
|  | 13469 |  | 
|  | 13470 | return EvaluateAsRValue(Info, E, Result.Val); | 
|  | 13471 | } | 
|  | 13472 |  | 
|  | 13473 | static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult, | 
|  | 13474 | const ASTContext &Ctx, | 
|  | 13475 | Expr::SideEffectsKind AllowSideEffects, | 
|  | 13476 | EvalInfo &Info) { | 
|  | 13477 | if (!E->getType()->isIntegralOrEnumerationType()) | 
|  | 13478 | return false; | 
|  | 13479 |  | 
|  | 13480 | if (!::EvaluateAsRValue(E, ExprResult, Ctx, Info) || | 
|  | 13481 | !ExprResult.Val.isInt() || | 
|  | 13482 | hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) | 
|  | 13483 | return false; | 
|  | 13484 |  | 
|  | 13485 | return true; | 
|  | 13486 | } | 
| Fariborz Jahanian | e735ff9 | 2013-01-24 22:11:45 +0000 | [diff] [blame] | 13487 |  | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 13488 | static bool EvaluateAsFixedPoint(const Expr *E, Expr::EvalResult &ExprResult, | 
|  | 13489 | const ASTContext &Ctx, | 
|  | 13490 | Expr::SideEffectsKind AllowSideEffects, | 
|  | 13491 | EvalInfo &Info) { | 
|  | 13492 | if (!E->getType()->isFixedPointType()) | 
|  | 13493 | return false; | 
|  | 13494 |  | 
|  | 13495 | if (!::EvaluateAsRValue(E, ExprResult, Ctx, Info)) | 
|  | 13496 | return false; | 
|  | 13497 |  | 
|  | 13498 | if (!ExprResult.Val.isFixedPoint() || | 
|  | 13499 | hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) | 
|  | 13500 | return false; | 
|  | 13501 |  | 
|  | 13502 | return true; | 
|  | 13503 | } | 
|  | 13504 |  | 
| Richard Smith | 7b553f1 | 2011-10-29 00:50:52 +0000 | [diff] [blame] | 13505 | /// EvaluateAsRValue - Return true if this is a constant which we can fold using | 
| John McCall | c07a0c7 | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 13506 | /// any crazy technique (that has nothing to do with language standards) that | 
|  | 13507 | /// we want to.  If this function returns true, it returns the folded constant | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 13508 | /// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion | 
|  | 13509 | /// will be applied to the result. | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13510 | bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, | 
|  | 13511 | bool InConstantContext) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13512 | assert(!isValueDependent() && | 
|  | 13513 | "Expression evaluator can't be called on a dependent expression."); | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 13514 | EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13515 | Info.InConstantContext = InConstantContext; | 
|  | 13516 | return ::EvaluateAsRValue(this, Result, Ctx, Info); | 
| John McCall | c07a0c7 | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 13517 | } | 
|  | 13518 |  | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13519 | bool Expr::EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, | 
|  | 13520 | bool InConstantContext) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13521 | assert(!isValueDependent() && | 
|  | 13522 | "Expression evaluator can't be called on a dependent expression."); | 
| Richard Smith | 11562c5 | 2011-10-28 17:51:58 +0000 | [diff] [blame] | 13523 | EvalResult Scratch; | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13524 | return EvaluateAsRValue(Scratch, Ctx, InConstantContext) && | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 13525 | HandleConversionToBool(Scratch.Val, Result); | 
| John McCall | 1be1c63 | 2010-01-05 23:42:56 +0000 | [diff] [blame] | 13526 | } | 
|  | 13527 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13528 | bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13529 | SideEffectsKind AllowSideEffects, | 
|  | 13530 | bool InConstantContext) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13531 | assert(!isValueDependent() && | 
|  | 13532 | "Expression evaluator can't be called on a dependent expression."); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13533 | EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13534 | Info.InConstantContext = InConstantContext; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13535 | return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info); | 
| Richard Smith | caf3390 | 2011-10-10 18:28:20 +0000 | [diff] [blame] | 13536 | } | 
|  | 13537 |  | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 13538 | bool Expr::EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13539 | SideEffectsKind AllowSideEffects, | 
|  | 13540 | bool InConstantContext) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13541 | assert(!isValueDependent() && | 
|  | 13542 | "Expression evaluator can't be called on a dependent expression."); | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 13543 | EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13544 | Info.InConstantContext = InConstantContext; | 
| Leonard Chan | d3f3e16 | 2019-01-18 21:04:25 +0000 | [diff] [blame] | 13545 | return ::EvaluateAsFixedPoint(this, Result, Ctx, AllowSideEffects, Info); | 
|  | 13546 | } | 
|  | 13547 |  | 
| Richard Trieu | be234c3 | 2016-04-21 21:04:55 +0000 | [diff] [blame] | 13548 | bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13549 | SideEffectsKind AllowSideEffects, | 
|  | 13550 | bool InConstantContext) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13551 | assert(!isValueDependent() && | 
|  | 13552 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 13553 |  | 
| Richard Trieu | be234c3 | 2016-04-21 21:04:55 +0000 | [diff] [blame] | 13554 | if (!getType()->isRealFloatingType()) | 
|  | 13555 | return false; | 
|  | 13556 |  | 
|  | 13557 | EvalResult ExprResult; | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13558 | if (!EvaluateAsRValue(ExprResult, Ctx, InConstantContext) || | 
|  | 13559 | !ExprResult.Val.isFloat() || | 
| Richard Smith | 3f1d6de | 2018-05-21 20:36:58 +0000 | [diff] [blame] | 13560 | hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) | 
| Richard Trieu | be234c3 | 2016-04-21 21:04:55 +0000 | [diff] [blame] | 13561 | return false; | 
|  | 13562 |  | 
|  | 13563 | Result = ExprResult.Val.getFloat(); | 
|  | 13564 | return true; | 
|  | 13565 | } | 
|  | 13566 |  | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13567 | bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, | 
|  | 13568 | bool InConstantContext) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13569 | assert(!isValueDependent() && | 
|  | 13570 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 13571 |  | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 13572 | EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold); | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 13573 | Info.InConstantContext = InConstantContext; | 
| John McCall | 45d55e4 | 2010-05-07 21:00:08 +0000 | [diff] [blame] | 13574 | LValue LV; | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 13575 | CheckedTemporaries CheckedTemps; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 13576 | if (!EvaluateLValue(this, LV, Info) || !Info.discardCleanups() || | 
|  | 13577 | Result.HasSideEffects || | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 13578 | !CheckLValueConstantExpression(Info, getExprLoc(), | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 13579 | Ctx.getLValueReferenceType(getType()), LV, | 
| Richard Smith | 4566f87 | 2019-09-29 05:58:31 +0000 | [diff] [blame] | 13580 | Expr::EvaluateForCodeGen, CheckedTemps)) | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 13581 | return false; | 
|  | 13582 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 13583 | LV.moveInto(Result.Val); | 
| Richard Smith | b228a86 | 2012-02-15 02:18:13 +0000 | [diff] [blame] | 13584 | return true; | 
| Eli Friedman | 7d45c48 | 2009-09-13 10:17:44 +0000 | [diff] [blame] | 13585 | } | 
|  | 13586 |  | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 13587 | bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage, | 
|  | 13588 | const ASTContext &Ctx) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13589 | assert(!isValueDependent() && | 
|  | 13590 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 13591 |  | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 13592 | EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression; | 
|  | 13593 | EvalInfo Info(Ctx, Result, EM); | 
| Eric Fiselier | 680e865 | 2019-03-08 22:06:48 +0000 | [diff] [blame] | 13594 | Info.InConstantContext = true; | 
| Eric Fiselier | add16a8 | 2019-04-24 02:23:30 +0000 | [diff] [blame] | 13595 |  | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13596 | if (!::Evaluate(Result.Val, Info, this) || Result.HasSideEffects) | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 13597 | return false; | 
|  | 13598 |  | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 13599 | if (!Info.discardCleanups()) | 
|  | 13600 | llvm_unreachable("Unhandled cleanup; missing full expression marker?"); | 
|  | 13601 |  | 
| Richard Smith | 5769440 | 2019-10-08 23:37:49 +0000 | [diff] [blame] | 13602 | return CheckConstantExpression(Info, getExprLoc(), getStorageType(Ctx, this), | 
|  | 13603 | Result.Val, Usage) && | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13604 | CheckMemoryLeaks(Info); | 
| Reid Kleckner | 1a840d2 | 2018-05-10 18:57:35 +0000 | [diff] [blame] | 13605 | } | 
|  | 13606 |  | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 13607 | bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, | 
|  | 13608 | const VarDecl *VD, | 
| Dmitri Gribenko | f857950 | 2013-01-12 19:30:44 +0000 | [diff] [blame] | 13609 | SmallVectorImpl<PartialDiagnosticAt> &Notes) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13610 | assert(!isValueDependent() && | 
|  | 13611 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 13612 |  | 
| Richard Smith | dafff94 | 2012-01-14 04:30:29 +0000 | [diff] [blame] | 13613 | // FIXME: Evaluating initializers for large array and record types can cause | 
|  | 13614 | // performance problems. Only do so in C++11 for now. | 
|  | 13615 | if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 13616 | !Ctx.getLangOpts().CPlusPlus11) | 
| Richard Smith | dafff94 | 2012-01-14 04:30:29 +0000 | [diff] [blame] | 13617 | return false; | 
|  | 13618 |  | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 13619 | Expr::EvalStatus EStatus; | 
|  | 13620 | EStatus.Diag = &Notes; | 
|  | 13621 |  | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 13622 | EvalInfo Info(Ctx, EStatus, VD->isConstexpr() | 
| Richard Smith | 0c6124b | 2015-12-03 01:36:22 +0000 | [diff] [blame] | 13623 | ? EvalInfo::EM_ConstantExpression | 
|  | 13624 | : EvalInfo::EM_ConstantFold); | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 13625 | Info.setEvaluatingDecl(VD, Value); | 
|  | 13626 | Info.InConstantContext = true; | 
|  | 13627 |  | 
|  | 13628 | SourceLocation DeclLoc = VD->getLocation(); | 
|  | 13629 | QualType DeclTy = VD->getType(); | 
|  | 13630 |  | 
|  | 13631 | if (Info.EnableNewConstInterp) { | 
|  | 13632 | auto &InterpCtx = const_cast<ASTContext &>(Ctx).getInterpContext(); | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 13633 | if (!InterpCtx.evaluateAsInitializer(Info, VD, Value)) | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 13634 | return false; | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 13635 | } else { | 
|  | 13636 | LValue LVal; | 
|  | 13637 | LVal.set(VD); | 
|  | 13638 |  | 
|  | 13639 | // C++11 [basic.start.init]p2: | 
|  | 13640 | //  Variables with static storage duration or thread storage duration shall | 
|  | 13641 | //  be zero-initialized before any other initialization takes place. | 
|  | 13642 | // This behavior is not present in C. | 
|  | 13643 | if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() && | 
|  | 13644 | !DeclTy->isReferenceType()) { | 
|  | 13645 | ImplicitValueInitExpr VIE(DeclTy); | 
|  | 13646 | if (!EvaluateInPlace(Value, Info, LVal, &VIE, | 
|  | 13647 | /*AllowNonLiteralTypes=*/true)) | 
|  | 13648 | return false; | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 13649 | } | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 13650 |  | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 13651 | if (!EvaluateInPlace(Value, Info, LVal, this, | 
|  | 13652 | /*AllowNonLiteralTypes=*/true) || | 
|  | 13653 | EStatus.HasSideEffects) | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 13654 | return false; | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 13655 |  | 
|  | 13656 | // At this point, any lifetime-extended temporaries are completely | 
|  | 13657 | // initialized. | 
|  | 13658 | Info.performLifetimeExtension(); | 
|  | 13659 |  | 
|  | 13660 | if (!Info.discardCleanups()) | 
|  | 13661 | llvm_unreachable("Unhandled cleanup; missing full expression marker?"); | 
| Richard Smith | fddd384 | 2011-12-30 21:15:51 +0000 | [diff] [blame] | 13662 | } | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 13663 | return CheckConstantExpression(Info, DeclLoc, DeclTy, Value) && | 
|  | 13664 | CheckMemoryLeaks(Info); | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 13665 | } | 
|  | 13666 |  | 
| Richard Smith | 2b4fa53 | 2019-09-29 05:08:46 +0000 | [diff] [blame] | 13667 | bool VarDecl::evaluateDestruction( | 
|  | 13668 | SmallVectorImpl<PartialDiagnosticAt> &Notes) const { | 
|  | 13669 | assert(getEvaluatedValue() && !getEvaluatedValue()->isAbsent() && | 
|  | 13670 | "cannot evaluate destruction of non-constant-initialized variable"); | 
|  | 13671 |  | 
|  | 13672 | Expr::EvalStatus EStatus; | 
|  | 13673 | EStatus.Diag = &Notes; | 
|  | 13674 |  | 
|  | 13675 | // Make a copy of the value for the destructor to mutate. | 
|  | 13676 | APValue DestroyedValue = *getEvaluatedValue(); | 
|  | 13677 |  | 
|  | 13678 | EvalInfo Info(getASTContext(), EStatus, EvalInfo::EM_ConstantExpression); | 
|  | 13679 | Info.setEvaluatingDecl(this, DestroyedValue, | 
|  | 13680 | EvalInfo::EvaluatingDeclKind::Dtor); | 
|  | 13681 | Info.InConstantContext = true; | 
|  | 13682 |  | 
|  | 13683 | SourceLocation DeclLoc = getLocation(); | 
|  | 13684 | QualType DeclTy = getType(); | 
|  | 13685 |  | 
|  | 13686 | LValue LVal; | 
|  | 13687 | LVal.set(this); | 
|  | 13688 |  | 
|  | 13689 | // FIXME: Consider storing whether this variable has constant destruction in | 
|  | 13690 | // the EvaluatedStmt so that CodeGen can query it. | 
|  | 13691 | if (!HandleDestruction(Info, DeclLoc, LVal.Base, DestroyedValue, DeclTy) || | 
|  | 13692 | EStatus.HasSideEffects) | 
|  | 13693 | return false; | 
|  | 13694 |  | 
|  | 13695 | if (!Info.discardCleanups()) | 
|  | 13696 | llvm_unreachable("Unhandled cleanup; missing full expression marker?"); | 
|  | 13697 |  | 
|  | 13698 | ensureEvaluatedStmt()->HasConstantDestruction = true; | 
|  | 13699 | return true; | 
|  | 13700 | } | 
|  | 13701 |  | 
| Richard Smith | 7b553f1 | 2011-10-29 00:50:52 +0000 | [diff] [blame] | 13702 | /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be | 
|  | 13703 | /// constant folded, but discard the result. | 
| Richard Smith | ce8eca5 | 2015-12-08 03:21:47 +0000 | [diff] [blame] | 13704 | bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13705 | assert(!isValueDependent() && | 
|  | 13706 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 13707 |  | 
| Anders Carlsson | 5b3638b | 2008-12-01 06:44:05 +0000 | [diff] [blame] | 13708 | EvalResult Result; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13709 | return EvaluateAsRValue(Result, Ctx, /* in constant context */ true) && | 
| Richard Smith | 3f1d6de | 2018-05-21 20:36:58 +0000 | [diff] [blame] | 13710 | !hasUnacceptableSideEffect(Result, SEK); | 
| Chris Lattner | cb13691 | 2008-10-06 06:49:02 +0000 | [diff] [blame] | 13711 | } | 
| Anders Carlsson | 59689ed | 2008-11-22 21:04:56 +0000 | [diff] [blame] | 13712 |  | 
| Fariborz Jahanian | 8b115b7 | 2013-01-09 23:04:56 +0000 | [diff] [blame] | 13713 | APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, | 
| Dmitri Gribenko | f857950 | 2013-01-12 19:30:44 +0000 | [diff] [blame] | 13714 | SmallVectorImpl<PartialDiagnosticAt> *Diag) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13715 | assert(!isValueDependent() && | 
|  | 13716 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 13717 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13718 | EvalResult EVResult; | 
|  | 13719 | EVResult.Diag = Diag; | 
|  | 13720 | EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); | 
|  | 13721 | Info.InConstantContext = true; | 
|  | 13722 |  | 
|  | 13723 | bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info); | 
| Jeffrey Yasskin | b332153 | 2010-12-23 01:01:28 +0000 | [diff] [blame] | 13724 | (void)Result; | 
| Anders Carlsson | 59689ed | 2008-11-22 21:04:56 +0000 | [diff] [blame] | 13725 | assert(Result && "Could not evaluate expression"); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13726 | assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); | 
| Anders Carlsson | 59689ed | 2008-11-22 21:04:56 +0000 | [diff] [blame] | 13727 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13728 | return EVResult.Val.getInt(); | 
| Anders Carlsson | 59689ed | 2008-11-22 21:04:56 +0000 | [diff] [blame] | 13729 | } | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13730 |  | 
| David Bolvansky | 3b6ae57 | 2018-10-18 20:49:06 +0000 | [diff] [blame] | 13731 | APSInt Expr::EvaluateKnownConstIntCheckOverflow( | 
|  | 13732 | const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13733 | assert(!isValueDependent() && | 
|  | 13734 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 13735 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13736 | EvalResult EVResult; | 
|  | 13737 | EVResult.Diag = Diag; | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 13738 | EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13739 | Info.InConstantContext = true; | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 13740 | Info.CheckingForUndefinedBehavior = true; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13741 |  | 
|  | 13742 | bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val); | 
| David Bolvansky | 3b6ae57 | 2018-10-18 20:49:06 +0000 | [diff] [blame] | 13743 | (void)Result; | 
|  | 13744 | assert(Result && "Could not evaluate expression"); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13745 | assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); | 
| David Bolvansky | 3b6ae57 | 2018-10-18 20:49:06 +0000 | [diff] [blame] | 13746 |  | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13747 | return EVResult.Val.getInt(); | 
| David Bolvansky | 3b6ae57 | 2018-10-18 20:49:06 +0000 | [diff] [blame] | 13748 | } | 
|  | 13749 |  | 
| Richard Smith | e9ff770 | 2013-11-05 22:23:30 +0000 | [diff] [blame] | 13750 | void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 13751 | assert(!isValueDependent() && | 
|  | 13752 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 13753 |  | 
| Fariborz Jahanian | e735ff9 | 2013-01-24 22:11:45 +0000 | [diff] [blame] | 13754 | bool IsConst; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13755 | EvalResult EVResult; | 
|  | 13756 | if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) { | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 13757 | EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); | 
|  | 13758 | Info.CheckingForUndefinedBehavior = true; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13759 | (void)::EvaluateAsRValue(Info, this, EVResult.Val); | 
| Fariborz Jahanian | e735ff9 | 2013-01-24 22:11:45 +0000 | [diff] [blame] | 13760 | } | 
|  | 13761 | } | 
|  | 13762 |  | 
| Richard Smith | e6c0144 | 2013-06-05 00:46:14 +0000 | [diff] [blame] | 13763 | bool Expr::EvalResult::isGlobalLValue() const { | 
|  | 13764 | assert(Val.isLValue()); | 
|  | 13765 | return IsGlobalLValue(Val.getLValueBase()); | 
|  | 13766 | } | 
| Abramo Bagnara | f819945 | 2010-05-14 17:07:14 +0000 | [diff] [blame] | 13767 |  | 
|  | 13768 |  | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13769 | /// isIntegerConstantExpr - this recursive routine will test if an expression is | 
|  | 13770 | /// an integer constant expression. | 
|  | 13771 |  | 
|  | 13772 | /// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero, | 
|  | 13773 | /// comma, etc | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13774 |  | 
|  | 13775 | // CheckICE - This function does the fundamental ICE checking: the returned | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13776 | // ICEDiag contains an ICEKind indicating whether the expression is an ICE, | 
|  | 13777 | // and a (possibly null) SourceLocation indicating the location of the problem. | 
|  | 13778 | // | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13779 | // Note that to reduce code duplication, this helper does no evaluation | 
|  | 13780 | // itself; the caller checks whether the expression is evaluatable, and | 
|  | 13781 | // in the rare cases where CheckICE actually cares about the evaluated | 
| George Burgess IV | 5731707 | 2017-02-02 07:53:55 +0000 | [diff] [blame] | 13782 | // value, it calls into Evaluate. | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13783 |  | 
| Dan Gohman | 28ade55 | 2010-07-26 21:25:24 +0000 | [diff] [blame] | 13784 | namespace { | 
|  | 13785 |  | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13786 | enum ICEKind { | 
|  | 13787 | /// This expression is an ICE. | 
|  | 13788 | IK_ICE, | 
|  | 13789 | /// This expression is not an ICE, but if it isn't evaluated, it's | 
|  | 13790 | /// a legal subexpression for an ICE. This return value is used to handle | 
|  | 13791 | /// the comma operator in C99 mode, and non-constant subexpressions. | 
|  | 13792 | IK_ICEIfUnevaluated, | 
|  | 13793 | /// This expression is not an ICE, and is not a legal subexpression for one. | 
|  | 13794 | IK_NotICE | 
|  | 13795 | }; | 
|  | 13796 |  | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13797 | struct ICEDiag { | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13798 | ICEKind Kind; | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13799 | SourceLocation Loc; | 
|  | 13800 |  | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13801 | ICEDiag(ICEKind IK, SourceLocation l) : Kind(IK), Loc(l) {} | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13802 | }; | 
|  | 13803 |  | 
| Alexander Kornienko | ab9db51 | 2015-06-22 23:07:51 +0000 | [diff] [blame] | 13804 | } | 
| Dan Gohman | 28ade55 | 2010-07-26 21:25:24 +0000 | [diff] [blame] | 13805 |  | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13806 | static ICEDiag NoDiag() { return ICEDiag(IK_ICE, SourceLocation()); } | 
|  | 13807 |  | 
|  | 13808 | static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13809 |  | 
| Craig Topper | a31a882 | 2013-08-22 07:09:37 +0000 | [diff] [blame] | 13810 | static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13811 | Expr::EvalResult EVResult; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 13812 | Expr::EvalStatus Status; | 
|  | 13813 | EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); | 
|  | 13814 |  | 
|  | 13815 | Info.InConstantContext = true; | 
|  | 13816 | if (!::EvaluateAsRValue(E, EVResult, Ctx, Info) || EVResult.HasSideEffects || | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13817 | !EVResult.Val.isInt()) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 13818 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13819 |  | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13820 | return NoDiag(); | 
|  | 13821 | } | 
|  | 13822 |  | 
| Craig Topper | a31a882 | 2013-08-22 07:09:37 +0000 | [diff] [blame] | 13823 | static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13824 | assert(!E->isValueDependent() && "Should not see value dependent exprs!"); | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13825 | if (!E->getType()->isIntegralOrEnumerationType()) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 13826 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13827 |  | 
|  | 13828 | switch (E->getStmtClass()) { | 
| John McCall | bd06678 | 2011-02-09 08:16:59 +0000 | [diff] [blame] | 13829 | #define ABSTRACT_STMT(Node) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13830 | #define STMT(Node, Base) case Expr::Node##Class: | 
|  | 13831 | #define EXPR(Node, Base) | 
|  | 13832 | #include "clang/AST/StmtNodes.inc" | 
|  | 13833 | case Expr::PredefinedExprClass: | 
|  | 13834 | case Expr::FloatingLiteralClass: | 
|  | 13835 | case Expr::ImaginaryLiteralClass: | 
|  | 13836 | case Expr::StringLiteralClass: | 
|  | 13837 | case Expr::ArraySubscriptExprClass: | 
| Alexey Bataev | 1a3320e | 2015-08-25 14:24:04 +0000 | [diff] [blame] | 13838 | case Expr::OMPArraySectionExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13839 | case Expr::MemberExprClass: | 
|  | 13840 | case Expr::CompoundAssignOperatorClass: | 
|  | 13841 | case Expr::CompoundLiteralExprClass: | 
|  | 13842 | case Expr::ExtVectorElementExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13843 | case Expr::DesignatedInitExprClass: | 
| Richard Smith | 410306b | 2016-12-12 02:53:20 +0000 | [diff] [blame] | 13844 | case Expr::ArrayInitLoopExprClass: | 
|  | 13845 | case Expr::ArrayInitIndexExprClass: | 
| Yunzhong Gao | cb77930 | 2015-06-10 00:27:52 +0000 | [diff] [blame] | 13846 | case Expr::NoInitExprClass: | 
|  | 13847 | case Expr::DesignatedInitUpdateExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13848 | case Expr::ImplicitValueInitExprClass: | 
|  | 13849 | case Expr::ParenListExprClass: | 
|  | 13850 | case Expr::VAArgExprClass: | 
|  | 13851 | case Expr::AddrLabelExprClass: | 
|  | 13852 | case Expr::StmtExprClass: | 
|  | 13853 | case Expr::CXXMemberCallExprClass: | 
| Peter Collingbourne | 41f8546 | 2011-02-09 21:07:24 +0000 | [diff] [blame] | 13854 | case Expr::CUDAKernelCallExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13855 | case Expr::CXXDynamicCastExprClass: | 
|  | 13856 | case Expr::CXXTypeidExprClass: | 
| Francois Pichet | 5cc0a67 | 2010-09-08 23:47:05 +0000 | [diff] [blame] | 13857 | case Expr::CXXUuidofExprClass: | 
| John McCall | 5e77d76 | 2013-04-16 07:28:30 +0000 | [diff] [blame] | 13858 | case Expr::MSPropertyRefExprClass: | 
| Alexey Bataev | f763027 | 2015-11-25 12:01:00 +0000 | [diff] [blame] | 13859 | case Expr::MSPropertySubscriptExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13860 | case Expr::CXXNullPtrLiteralExprClass: | 
| Richard Smith | c67fdd4 | 2012-03-07 08:35:16 +0000 | [diff] [blame] | 13861 | case Expr::UserDefinedLiteralClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13862 | case Expr::CXXThisExprClass: | 
|  | 13863 | case Expr::CXXThrowExprClass: | 
|  | 13864 | case Expr::CXXNewExprClass: | 
|  | 13865 | case Expr::CXXDeleteExprClass: | 
|  | 13866 | case Expr::CXXPseudoDestructorExprClass: | 
|  | 13867 | case Expr::UnresolvedLookupExprClass: | 
| Kaelyn Takata | e1f49d5 | 2014-10-27 18:07:20 +0000 | [diff] [blame] | 13868 | case Expr::TypoExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13869 | case Expr::DependentScopeDeclRefExprClass: | 
|  | 13870 | case Expr::CXXConstructExprClass: | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 13871 | case Expr::CXXInheritedCtorInitExprClass: | 
| Richard Smith | cc1b96d | 2013-06-12 22:31:48 +0000 | [diff] [blame] | 13872 | case Expr::CXXStdInitializerListExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13873 | case Expr::CXXBindTemporaryExprClass: | 
| John McCall | 5d41378 | 2010-12-06 08:20:24 +0000 | [diff] [blame] | 13874 | case Expr::ExprWithCleanupsClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13875 | case Expr::CXXTemporaryObjectExprClass: | 
|  | 13876 | case Expr::CXXUnresolvedConstructExprClass: | 
|  | 13877 | case Expr::CXXDependentScopeMemberExprClass: | 
|  | 13878 | case Expr::UnresolvedMemberExprClass: | 
|  | 13879 | case Expr::ObjCStringLiteralClass: | 
| Patrick Beard | 0caa394 | 2012-04-19 00:25:12 +0000 | [diff] [blame] | 13880 | case Expr::ObjCBoxedExprClass: | 
| Ted Kremenek | e65b086 | 2012-03-06 20:05:56 +0000 | [diff] [blame] | 13881 | case Expr::ObjCArrayLiteralClass: | 
|  | 13882 | case Expr::ObjCDictionaryLiteralClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13883 | case Expr::ObjCEncodeExprClass: | 
|  | 13884 | case Expr::ObjCMessageExprClass: | 
|  | 13885 | case Expr::ObjCSelectorExprClass: | 
|  | 13886 | case Expr::ObjCProtocolExprClass: | 
|  | 13887 | case Expr::ObjCIvarRefExprClass: | 
|  | 13888 | case Expr::ObjCPropertyRefExprClass: | 
| Ted Kremenek | e65b086 | 2012-03-06 20:05:56 +0000 | [diff] [blame] | 13889 | case Expr::ObjCSubscriptRefExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13890 | case Expr::ObjCIsaExprClass: | 
| Erik Pilkington | 29099de | 2016-07-16 00:35:23 +0000 | [diff] [blame] | 13891 | case Expr::ObjCAvailabilityCheckExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13892 | case Expr::ShuffleVectorExprClass: | 
| Hal Finkel | c4d7c82 | 2013-09-18 03:29:45 +0000 | [diff] [blame] | 13893 | case Expr::ConvertVectorExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13894 | case Expr::BlockExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13895 | case Expr::NoStmtClass: | 
| John McCall | 8d69a21 | 2010-11-15 23:31:06 +0000 | [diff] [blame] | 13896 | case Expr::OpaqueValueExprClass: | 
| Douglas Gregor | e8e9dd6 | 2011-01-03 17:17:50 +0000 | [diff] [blame] | 13897 | case Expr::PackExpansionExprClass: | 
| Douglas Gregor | cdbc539 | 2011-01-15 01:15:58 +0000 | [diff] [blame] | 13898 | case Expr::SubstNonTypeTemplateParmPackExprClass: | 
| Richard Smith | b15fe3a | 2012-09-12 00:56:43 +0000 | [diff] [blame] | 13899 | case Expr::FunctionParmPackExprClass: | 
| Tanya Lattner | 55808c1 | 2011-06-04 00:47:47 +0000 | [diff] [blame] | 13900 | case Expr::AsTypeExprClass: | 
| John McCall | 31168b0 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 13901 | case Expr::ObjCIndirectCopyRestoreExprClass: | 
| Douglas Gregor | fe31481 | 2011-06-21 17:03:29 +0000 | [diff] [blame] | 13902 | case Expr::MaterializeTemporaryExprClass: | 
| John McCall | fe96e0b | 2011-11-06 09:01:30 +0000 | [diff] [blame] | 13903 | case Expr::PseudoObjectExprClass: | 
| Eli Friedman | df14b3a | 2011-10-11 02:20:01 +0000 | [diff] [blame] | 13904 | case Expr::AtomicExprClass: | 
| Douglas Gregor | e31e606 | 2012-02-07 10:09:13 +0000 | [diff] [blame] | 13905 | case Expr::LambdaExprClass: | 
| Richard Smith | 0f0af19 | 2014-11-08 05:07:16 +0000 | [diff] [blame] | 13906 | case Expr::CXXFoldExprClass: | 
| Richard Smith | 9f690bd | 2015-10-27 06:02:45 +0000 | [diff] [blame] | 13907 | case Expr::CoawaitExprClass: | 
| Eric Fiselier | 20f25cb | 2017-03-06 23:38:15 +0000 | [diff] [blame] | 13908 | case Expr::DependentCoawaitExprClass: | 
| Richard Smith | 9f690bd | 2015-10-27 06:02:45 +0000 | [diff] [blame] | 13909 | case Expr::CoyieldExprClass: | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 13910 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| Sebastian Redl | 12757ab | 2011-09-24 17:48:14 +0000 | [diff] [blame] | 13911 |  | 
| Richard Smith | f137f93 | 2014-01-25 20:50:08 +0000 | [diff] [blame] | 13912 | case Expr::InitListExprClass: { | 
|  | 13913 | // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the | 
|  | 13914 | // form "T x = { a };" is equivalent to "T x = a;". | 
|  | 13915 | // Unless we're initializing a reference, T is a scalar as it is known to be | 
|  | 13916 | // of integral or enumeration type. | 
|  | 13917 | if (E->isRValue()) | 
|  | 13918 | if (cast<InitListExpr>(E)->getNumInits() == 1) | 
|  | 13919 | return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx); | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 13920 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| Richard Smith | f137f93 | 2014-01-25 20:50:08 +0000 | [diff] [blame] | 13921 | } | 
|  | 13922 |  | 
| Douglas Gregor | 820ba7b | 2011-01-04 17:33:58 +0000 | [diff] [blame] | 13923 | case Expr::SizeOfPackExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13924 | case Expr::GNUNullExprClass: | 
| Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 13925 | case Expr::SourceLocExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13926 | return NoDiag(); | 
|  | 13927 |  | 
| John McCall | 7c454bb | 2011-07-15 05:09:51 +0000 | [diff] [blame] | 13928 | case Expr::SubstNonTypeTemplateParmExprClass: | 
|  | 13929 | return | 
|  | 13930 | CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx); | 
|  | 13931 |  | 
| Bill Wendling | 7c44da2 | 2018-10-31 03:48:47 +0000 | [diff] [blame] | 13932 | case Expr::ConstantExprClass: | 
|  | 13933 | return CheckICE(cast<ConstantExpr>(E)->getSubExpr(), Ctx); | 
|  | 13934 |  | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13935 | case Expr::ParenExprClass: | 
|  | 13936 | return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx); | 
| Peter Collingbourne | 9114759 | 2011-04-15 00:35:48 +0000 | [diff] [blame] | 13937 | case Expr::GenericSelectionExprClass: | 
|  | 13938 | return CheckICE(cast<GenericSelectionExpr>(E)->getResultExpr(), Ctx); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13939 | case Expr::IntegerLiteralClass: | 
| Leonard Chan | db01c3a | 2018-06-20 17:19:40 +0000 | [diff] [blame] | 13940 | case Expr::FixedPointLiteralClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13941 | case Expr::CharacterLiteralClass: | 
| Ted Kremenek | e65b086 | 2012-03-06 20:05:56 +0000 | [diff] [blame] | 13942 | case Expr::ObjCBoolLiteralExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13943 | case Expr::CXXBoolLiteralExprClass: | 
| Douglas Gregor | 747eb78 | 2010-07-08 06:14:04 +0000 | [diff] [blame] | 13944 | case Expr::CXXScalarValueInitExprClass: | 
| Douglas Gregor | 29c42f2 | 2012-02-24 07:38:34 +0000 | [diff] [blame] | 13945 | case Expr::TypeTraitExprClass: | 
| Saar Raz | 5d98ba6 | 2019-10-15 15:24:26 +0000 | [diff] [blame] | 13946 | case Expr::ConceptSpecializationExprClass: | 
| John Wiegley | 6242b6a | 2011-04-28 00:16:57 +0000 | [diff] [blame] | 13947 | case Expr::ArrayTypeTraitExprClass: | 
| John Wiegley | f9f6584 | 2011-04-25 06:54:41 +0000 | [diff] [blame] | 13948 | case Expr::ExpressionTraitExprClass: | 
| Sebastian Redl | 4202c0f | 2010-09-10 20:55:43 +0000 | [diff] [blame] | 13949 | case Expr::CXXNoexceptExprClass: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13950 | return NoDiag(); | 
|  | 13951 | case Expr::CallExprClass: | 
| Alexis Hunt | 3b79186 | 2010-08-30 17:47:05 +0000 | [diff] [blame] | 13952 | case Expr::CXXOperatorCallExprClass: { | 
| Richard Smith | 62f6595 | 2011-10-24 22:35:48 +0000 | [diff] [blame] | 13953 | // C99 6.6/3 allows function calls within unevaluated subexpressions of | 
|  | 13954 | // constant expressions, but they can never be ICEs because an ICE cannot | 
|  | 13955 | // contain an operand of (pointer to) function type. | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13956 | const CallExpr *CE = cast<CallExpr>(E); | 
| Alp Toker | a724cff | 2013-12-28 21:59:02 +0000 | [diff] [blame] | 13957 | if (CE->getBuiltinCallee()) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13958 | return CheckEvalInICE(E, Ctx); | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 13959 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13960 | } | 
| Richard Smith | 778dc0f | 2019-10-19 00:04:38 +0000 | [diff] [blame] | 13961 | case Expr::CXXRewrittenBinaryOperatorClass: | 
|  | 13962 | return CheckICE(cast<CXXRewrittenBinaryOperator>(E)->getSemanticForm(), | 
|  | 13963 | Ctx); | 
| Richard Smith | 6365c91 | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 13964 | case Expr::DeclRefExprClass: { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13965 | if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) | 
|  | 13966 | return NoDiag(); | 
| George Burgess IV | 00f70bd | 2018-03-01 05:43:23 +0000 | [diff] [blame] | 13967 | const ValueDecl *D = cast<DeclRefExpr>(E)->getDecl(); | 
| David Blaikie | bbafb8a | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 13968 | if (Ctx.getLangOpts().CPlusPlus && | 
| Richard Smith | 6365c91 | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 13969 | D && IsConstNonVolatile(D->getType())) { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13970 | // Parameter variables are never constants.  Without this check, | 
|  | 13971 | // getAnyInitializer() can find a default argument, which leads | 
|  | 13972 | // to chaos. | 
|  | 13973 | if (isa<ParmVarDecl>(D)) | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13974 | return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13975 |  | 
|  | 13976 | // C++ 7.1.5.1p2 | 
|  | 13977 | //   A variable of non-volatile const-qualified integral or enumeration | 
|  | 13978 | //   type initialized by an ICE can be used in ICEs. | 
|  | 13979 | if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) { | 
| Richard Smith | ec8dcd2 | 2011-11-08 01:31:09 +0000 | [diff] [blame] | 13980 | if (!Dcl->getType()->isIntegralOrEnumerationType()) | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13981 | return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); | 
| Richard Smith | ec8dcd2 | 2011-11-08 01:31:09 +0000 | [diff] [blame] | 13982 |  | 
| Richard Smith | d0b4dd6 | 2011-12-19 06:19:21 +0000 | [diff] [blame] | 13983 | const VarDecl *VD; | 
|  | 13984 | // Look for a declaration of this variable that has an initializer, and | 
|  | 13985 | // check whether it is an ICE. | 
|  | 13986 | if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE()) | 
|  | 13987 | return NoDiag(); | 
|  | 13988 | else | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 13989 | return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13990 | } | 
|  | 13991 | } | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 13992 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| Richard Smith | 6365c91 | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 13993 | } | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 13994 | case Expr::UnaryOperatorClass: { | 
|  | 13995 | const UnaryOperator *Exp = cast<UnaryOperator>(E); | 
|  | 13996 | switch (Exp->getOpcode()) { | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 13997 | case UO_PostInc: | 
|  | 13998 | case UO_PostDec: | 
|  | 13999 | case UO_PreInc: | 
|  | 14000 | case UO_PreDec: | 
|  | 14001 | case UO_AddrOf: | 
|  | 14002 | case UO_Deref: | 
| Richard Smith | 9f690bd | 2015-10-27 06:02:45 +0000 | [diff] [blame] | 14003 | case UO_Coawait: | 
| Richard Smith | 62f6595 | 2011-10-24 22:35:48 +0000 | [diff] [blame] | 14004 | // C99 6.6/3 allows increment and decrement within unevaluated | 
|  | 14005 | // subexpressions of constant expressions, but they can never be ICEs | 
|  | 14006 | // because an ICE cannot contain an lvalue operand. | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14007 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 14008 | case UO_Extension: | 
|  | 14009 | case UO_LNot: | 
|  | 14010 | case UO_Plus: | 
|  | 14011 | case UO_Minus: | 
|  | 14012 | case UO_Not: | 
|  | 14013 | case UO_Real: | 
|  | 14014 | case UO_Imag: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14015 | return CheckICE(Exp->getSubExpr(), Ctx); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14016 | } | 
| Reid Kleckner | e540d97 | 2018-11-01 17:51:48 +0000 | [diff] [blame] | 14017 | llvm_unreachable("invalid unary operator class"); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14018 | } | 
|  | 14019 | case Expr::OffsetOfExprClass: { | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14020 | // Note that per C99, offsetof must be an ICE. And AFAIK, using | 
|  | 14021 | // EvaluateAsRValue matches the proposed gcc behavior for cases like | 
|  | 14022 | // "offsetof(struct s{int x[4];}, x[1.0])".  This doesn't affect | 
|  | 14023 | // compliance: we should warn earlier for offsetof expressions with | 
|  | 14024 | // array subscripts that aren't ICEs, and if the array subscripts | 
|  | 14025 | // are ICEs, the value of the offsetof must be an integer constant. | 
|  | 14026 | return CheckEvalInICE(E, Ctx); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14027 | } | 
| Peter Collingbourne | e190dee | 2011-03-11 19:24:49 +0000 | [diff] [blame] | 14028 | case Expr::UnaryExprOrTypeTraitExprClass: { | 
|  | 14029 | const UnaryExprOrTypeTraitExpr *Exp = cast<UnaryExprOrTypeTraitExpr>(E); | 
|  | 14030 | if ((Exp->getKind() ==  UETT_SizeOf) && | 
|  | 14031 | Exp->getTypeOfArgument()->isVariableArrayType()) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14032 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14033 | return NoDiag(); | 
|  | 14034 | } | 
|  | 14035 | case Expr::BinaryOperatorClass: { | 
|  | 14036 | const BinaryOperator *Exp = cast<BinaryOperator>(E); | 
|  | 14037 | switch (Exp->getOpcode()) { | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 14038 | case BO_PtrMemD: | 
|  | 14039 | case BO_PtrMemI: | 
|  | 14040 | case BO_Assign: | 
|  | 14041 | case BO_MulAssign: | 
|  | 14042 | case BO_DivAssign: | 
|  | 14043 | case BO_RemAssign: | 
|  | 14044 | case BO_AddAssign: | 
|  | 14045 | case BO_SubAssign: | 
|  | 14046 | case BO_ShlAssign: | 
|  | 14047 | case BO_ShrAssign: | 
|  | 14048 | case BO_AndAssign: | 
|  | 14049 | case BO_XorAssign: | 
|  | 14050 | case BO_OrAssign: | 
| Richard Smith | 62f6595 | 2011-10-24 22:35:48 +0000 | [diff] [blame] | 14051 | // C99 6.6/3 allows assignments within unevaluated subexpressions of | 
|  | 14052 | // constant expressions, but they can never be ICEs because an ICE cannot | 
|  | 14053 | // contain an lvalue operand. | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14054 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14055 |  | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 14056 | case BO_Mul: | 
|  | 14057 | case BO_Div: | 
|  | 14058 | case BO_Rem: | 
|  | 14059 | case BO_Add: | 
|  | 14060 | case BO_Sub: | 
|  | 14061 | case BO_Shl: | 
|  | 14062 | case BO_Shr: | 
|  | 14063 | case BO_LT: | 
|  | 14064 | case BO_GT: | 
|  | 14065 | case BO_LE: | 
|  | 14066 | case BO_GE: | 
|  | 14067 | case BO_EQ: | 
|  | 14068 | case BO_NE: | 
|  | 14069 | case BO_And: | 
|  | 14070 | case BO_Xor: | 
|  | 14071 | case BO_Or: | 
| Eric Fiselier | 0683c0e | 2018-05-07 21:07:10 +0000 | [diff] [blame] | 14072 | case BO_Comma: | 
|  | 14073 | case BO_Cmp: { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14074 | ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); | 
|  | 14075 | ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 14076 | if (Exp->getOpcode() == BO_Div || | 
|  | 14077 | Exp->getOpcode() == BO_Rem) { | 
| Richard Smith | 7b553f1 | 2011-10-29 00:50:52 +0000 | [diff] [blame] | 14078 | // EvaluateAsRValue gives an error for undefined Div/Rem, so make sure | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14079 | // we don't evaluate one. | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14080 | if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { | 
| Richard Smith | caf3390 | 2011-10-10 18:28:20 +0000 | [diff] [blame] | 14081 | llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14082 | if (REval == 0) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14083 | return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14084 | if (REval.isSigned() && REval.isAllOnesValue()) { | 
| Richard Smith | caf3390 | 2011-10-10 18:28:20 +0000 | [diff] [blame] | 14085 | llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14086 | if (LEval.isMinSignedValue()) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14087 | return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14088 | } | 
|  | 14089 | } | 
|  | 14090 | } | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 14091 | if (Exp->getOpcode() == BO_Comma) { | 
| David Blaikie | bbafb8a | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 14092 | if (Ctx.getLangOpts().C99) { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14093 | // C99 6.6p3 introduces a strange edge case: comma can be in an ICE | 
|  | 14094 | // if it isn't evaluated. | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14095 | if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14096 | return ICEDiag(IK_ICEIfUnevaluated, E->getBeginLoc()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14097 | } else { | 
|  | 14098 | // In both C89 and C++, commas in ICEs are illegal. | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14099 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14100 | } | 
|  | 14101 | } | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14102 | return Worst(LHSResult, RHSResult); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14103 | } | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 14104 | case BO_LAnd: | 
|  | 14105 | case BO_LOr: { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14106 | ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); | 
|  | 14107 | ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14108 | if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICEIfUnevaluated) { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14109 | // Rare case where the RHS has a comma "side-effect"; we need | 
|  | 14110 | // to actually check the condition to see whether the side | 
|  | 14111 | // with the comma is evaluated. | 
| John McCall | e302792 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 14112 | if ((Exp->getOpcode() == BO_LAnd) != | 
| Richard Smith | caf3390 | 2011-10-10 18:28:20 +0000 | [diff] [blame] | 14113 | (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14114 | return RHSResult; | 
|  | 14115 | return NoDiag(); | 
|  | 14116 | } | 
|  | 14117 |  | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14118 | return Worst(LHSResult, RHSResult); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14119 | } | 
|  | 14120 | } | 
| Reid Kleckner | e540d97 | 2018-11-01 17:51:48 +0000 | [diff] [blame] | 14121 | llvm_unreachable("invalid binary operator kind"); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14122 | } | 
|  | 14123 | case Expr::ImplicitCastExprClass: | 
|  | 14124 | case Expr::CStyleCastExprClass: | 
|  | 14125 | case Expr::CXXFunctionalCastExprClass: | 
|  | 14126 | case Expr::CXXStaticCastExprClass: | 
|  | 14127 | case Expr::CXXReinterpretCastExprClass: | 
| Richard Smith | c3e31e7 | 2011-10-24 18:26:35 +0000 | [diff] [blame] | 14128 | case Expr::CXXConstCastExprClass: | 
| John McCall | 31168b0 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 14129 | case Expr::ObjCBridgedCastExprClass: { | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14130 | const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr(); | 
| Richard Smith | 0b973d0 | 2011-12-18 02:33:09 +0000 | [diff] [blame] | 14131 | if (isa<ExplicitCastExpr>(E)) { | 
|  | 14132 | if (const FloatingLiteral *FL | 
|  | 14133 | = dyn_cast<FloatingLiteral>(SubExpr->IgnoreParenImpCasts())) { | 
|  | 14134 | unsigned DestWidth = Ctx.getIntWidth(E->getType()); | 
|  | 14135 | bool DestSigned = E->getType()->isSignedIntegerOrEnumerationType(); | 
|  | 14136 | APSInt IgnoredVal(DestWidth, !DestSigned); | 
|  | 14137 | bool Ignored; | 
|  | 14138 | // If the value does not fit in the destination type, the behavior is | 
|  | 14139 | // undefined, so we are not required to treat it as a constant | 
|  | 14140 | // expression. | 
|  | 14141 | if (FL->getValue().convertToInteger(IgnoredVal, | 
|  | 14142 | llvm::APFloat::rmTowardZero, | 
|  | 14143 | &Ignored) & APFloat::opInvalidOp) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14144 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| Richard Smith | 0b973d0 | 2011-12-18 02:33:09 +0000 | [diff] [blame] | 14145 | return NoDiag(); | 
|  | 14146 | } | 
|  | 14147 | } | 
| Eli Friedman | 76d4e43 | 2011-09-29 21:49:34 +0000 | [diff] [blame] | 14148 | switch (cast<CastExpr>(E)->getCastKind()) { | 
|  | 14149 | case CK_LValueToRValue: | 
| David Chisnall | fa35df6 | 2012-01-16 17:27:18 +0000 | [diff] [blame] | 14150 | case CK_AtomicToNonAtomic: | 
|  | 14151 | case CK_NonAtomicToAtomic: | 
| Eli Friedman | 76d4e43 | 2011-09-29 21:49:34 +0000 | [diff] [blame] | 14152 | case CK_NoOp: | 
|  | 14153 | case CK_IntegralToBoolean: | 
|  | 14154 | case CK_IntegralCast: | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14155 | return CheckICE(SubExpr, Ctx); | 
| Eli Friedman | 76d4e43 | 2011-09-29 21:49:34 +0000 | [diff] [blame] | 14156 | default: | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 14157 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
| Eli Friedman | 76d4e43 | 2011-09-29 21:49:34 +0000 | [diff] [blame] | 14158 | } | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14159 | } | 
| John McCall | c07a0c7 | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 14160 | case Expr::BinaryConditionalOperatorClass: { | 
|  | 14161 | const BinaryConditionalOperator *Exp = cast<BinaryConditionalOperator>(E); | 
|  | 14162 | ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx); | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14163 | if (CommonResult.Kind == IK_NotICE) return CommonResult; | 
| John McCall | c07a0c7 | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 14164 | ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14165 | if (FalseResult.Kind == IK_NotICE) return FalseResult; | 
|  | 14166 | if (CommonResult.Kind == IK_ICEIfUnevaluated) return CommonResult; | 
|  | 14167 | if (FalseResult.Kind == IK_ICEIfUnevaluated && | 
| Richard Smith | 74fc721 | 2012-12-28 12:53:55 +0000 | [diff] [blame] | 14168 | Exp->getCommon()->EvaluateKnownConstInt(Ctx) != 0) return NoDiag(); | 
| John McCall | c07a0c7 | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 14169 | return FalseResult; | 
|  | 14170 | } | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14171 | case Expr::ConditionalOperatorClass: { | 
|  | 14172 | const ConditionalOperator *Exp = cast<ConditionalOperator>(E); | 
|  | 14173 | // If the condition (ignoring parens) is a __builtin_constant_p call, | 
|  | 14174 | // then only the true side is actually considered in an integer constant | 
|  | 14175 | // expression, and it is fully evaluated.  This is an important GNU | 
|  | 14176 | // extension.  See GCC PR38377 for discussion. | 
|  | 14177 | if (const CallExpr *CallCE | 
|  | 14178 | = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts())) | 
| Alp Toker | a724cff | 2013-12-28 21:59:02 +0000 | [diff] [blame] | 14179 | if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) | 
| Richard Smith | 5fab0c9 | 2011-12-28 19:48:30 +0000 | [diff] [blame] | 14180 | return CheckEvalInICE(E, Ctx); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14181 | ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14182 | if (CondResult.Kind == IK_NotICE) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14183 | return CondResult; | 
| Douglas Gregor | fcafc6e | 2011-05-24 16:02:01 +0000 | [diff] [blame] | 14184 |  | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14185 | ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); | 
|  | 14186 | ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); | 
| Douglas Gregor | fcafc6e | 2011-05-24 16:02:01 +0000 | [diff] [blame] | 14187 |  | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14188 | if (TrueResult.Kind == IK_NotICE) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14189 | return TrueResult; | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14190 | if (FalseResult.Kind == IK_NotICE) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14191 | return FalseResult; | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14192 | if (CondResult.Kind == IK_ICEIfUnevaluated) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14193 | return CondResult; | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14194 | if (TrueResult.Kind == IK_ICE && FalseResult.Kind == IK_ICE) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14195 | return NoDiag(); | 
|  | 14196 | // Rare case where the diagnostics depend on which side is evaluated | 
|  | 14197 | // Note that if we get here, CondResult is 0, and at least one of | 
|  | 14198 | // TrueResult and FalseResult is non-zero. | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14199 | if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14200 | return FalseResult; | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14201 | return TrueResult; | 
|  | 14202 | } | 
|  | 14203 | case Expr::CXXDefaultArgExprClass: | 
|  | 14204 | return CheckICE(cast<CXXDefaultArgExpr>(E)->getExpr(), Ctx); | 
| Richard Smith | 852c9db | 2013-04-20 22:23:05 +0000 | [diff] [blame] | 14205 | case Expr::CXXDefaultInitExprClass: | 
|  | 14206 | return CheckICE(cast<CXXDefaultInitExpr>(E)->getExpr(), Ctx); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14207 | case Expr::ChooseExprClass: { | 
| Eli Friedman | 75807f2 | 2013-07-20 00:40:58 +0000 | [diff] [blame] | 14208 | return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(), Ctx); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14209 | } | 
| Erik Pilkington | eee944e | 2019-07-02 18:28:13 +0000 | [diff] [blame] | 14210 | case Expr::BuiltinBitCastExprClass: { | 
|  | 14211 | if (!checkBitCastConstexprEligibility(nullptr, Ctx, cast<CastExpr>(E))) | 
|  | 14212 | return ICEDiag(IK_NotICE, E->getBeginLoc()); | 
|  | 14213 | return CheckICE(cast<CastExpr>(E)->getSubExpr(), Ctx); | 
|  | 14214 | } | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14215 | } | 
|  | 14216 |  | 
| David Blaikie | e4d798f | 2012-01-20 21:50:17 +0000 | [diff] [blame] | 14217 | llvm_unreachable("Invalid StmtClass!"); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14218 | } | 
|  | 14219 |  | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14220 | /// Evaluate an expression as a C++11 integral constant expression. | 
| Craig Topper | a31a882 | 2013-08-22 07:09:37 +0000 | [diff] [blame] | 14221 | static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14222 | const Expr *E, | 
|  | 14223 | llvm::APSInt *Value, | 
|  | 14224 | SourceLocation *Loc) { | 
| Erich Keane | 1ddd4bf | 2018-07-20 17:42:09 +0000 | [diff] [blame] | 14225 | if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14226 | if (Loc) *Loc = E->getExprLoc(); | 
|  | 14227 | return false; | 
|  | 14228 | } | 
|  | 14229 |  | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14230 | APValue Result; | 
|  | 14231 | if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc)) | 
| Richard Smith | 92b1ce0 | 2011-12-12 09:28:41 +0000 | [diff] [blame] | 14232 | return false; | 
|  | 14233 |  | 
| Richard Smith | 98710fc | 2014-11-13 23:03:19 +0000 | [diff] [blame] | 14234 | if (!Result.isInt()) { | 
|  | 14235 | if (Loc) *Loc = E->getExprLoc(); | 
|  | 14236 | return false; | 
|  | 14237 | } | 
|  | 14238 |  | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14239 | if (Value) *Value = Result.getInt(); | 
| Richard Smith | 92b1ce0 | 2011-12-12 09:28:41 +0000 | [diff] [blame] | 14240 | return true; | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14241 | } | 
|  | 14242 |  | 
| Craig Topper | a31a882 | 2013-08-22 07:09:37 +0000 | [diff] [blame] | 14243 | bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, | 
|  | 14244 | SourceLocation *Loc) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 14245 | assert(!isValueDependent() && | 
|  | 14246 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 14247 |  | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 14248 | if (Ctx.getLangOpts().CPlusPlus11) | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 14249 | return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc); | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14250 |  | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14251 | ICEDiag D = CheckICE(this, Ctx); | 
|  | 14252 | if (D.Kind != IK_ICE) { | 
|  | 14253 | if (Loc) *Loc = D.Loc; | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14254 | return false; | 
|  | 14255 | } | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14256 | return true; | 
|  | 14257 | } | 
|  | 14258 |  | 
| Craig Topper | a31a882 | 2013-08-22 07:09:37 +0000 | [diff] [blame] | 14259 | bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14260 | SourceLocation *Loc, bool isEvaluated) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 14261 | assert(!isValueDependent() && | 
|  | 14262 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 14263 |  | 
| Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 14264 | if (Ctx.getLangOpts().CPlusPlus11) | 
| Richard Smith | f57d8cb | 2011-12-09 22:58:01 +0000 | [diff] [blame] | 14265 | return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); | 
|  | 14266 |  | 
|  | 14267 | if (!isIntegerConstantExpr(Ctx, Loc)) | 
|  | 14268 | return false; | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 14269 |  | 
| Richard Smith | 5c40f09 | 2015-12-04 03:00:44 +0000 | [diff] [blame] | 14270 | // The only possible side-effects here are due to UB discovered in the | 
|  | 14271 | // evaluation (for instance, INT_MAX + 1). In such a case, we are still | 
|  | 14272 | // required to treat the expression as an ICE, so we produce the folded | 
|  | 14273 | // value. | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 14274 | EvalResult ExprResult; | 
|  | 14275 | Expr::EvalStatus Status; | 
|  | 14276 | EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects); | 
|  | 14277 | Info.InConstantContext = true; | 
|  | 14278 |  | 
|  | 14279 | if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info)) | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14280 | llvm_unreachable("ICE cannot be evaluated!"); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 14281 |  | 
|  | 14282 | Value = ExprResult.Val.getInt(); | 
| John McCall | 864e396 | 2010-05-07 05:32:02 +0000 | [diff] [blame] | 14283 | return true; | 
|  | 14284 | } | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14285 |  | 
| Craig Topper | a31a882 | 2013-08-22 07:09:37 +0000 | [diff] [blame] | 14286 | bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 14287 | assert(!isValueDependent() && | 
|  | 14288 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 14289 |  | 
| Richard Smith | 9e575da | 2012-12-28 13:25:52 +0000 | [diff] [blame] | 14290 | return CheckICE(this, Ctx).Kind == IK_ICE; | 
| Richard Smith | 98a0a49 | 2012-02-14 21:38:30 +0000 | [diff] [blame] | 14291 | } | 
|  | 14292 |  | 
| Craig Topper | a31a882 | 2013-08-22 07:09:37 +0000 | [diff] [blame] | 14293 | bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14294 | SourceLocation *Loc) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 14295 | assert(!isValueDependent() && | 
|  | 14296 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 14297 |  | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14298 | // We support this checking in C++98 mode in order to diagnose compatibility | 
|  | 14299 | // issues. | 
| David Blaikie | bbafb8a | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 14300 | assert(Ctx.getLangOpts().CPlusPlus); | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14301 |  | 
| Richard Smith | 98a0a49 | 2012-02-14 21:38:30 +0000 | [diff] [blame] | 14302 | // Build evaluation settings. | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14303 | Expr::EvalStatus Status; | 
| Dmitri Gribenko | f857950 | 2013-01-12 19:30:44 +0000 | [diff] [blame] | 14304 | SmallVector<PartialDiagnosticAt, 8> Diags; | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14305 | Status.Diag = &Diags; | 
| Richard Smith | 6d4c658 | 2013-11-05 22:18:15 +0000 | [diff] [blame] | 14306 | EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14307 |  | 
|  | 14308 | APValue Scratch; | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 14309 | bool IsConstExpr = | 
|  | 14310 | ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) && | 
|  | 14311 | // FIXME: We don't produce a diagnostic for this, but the callers that | 
|  | 14312 | // call us on arbitrary full-expressions should generally not care. | 
| Richard Smith | da1b434 | 2019-09-27 01:26:47 +0000 | [diff] [blame] | 14313 | Info.discardCleanups() && !Status.HasSideEffects; | 
| Richard Smith | 66e05fe | 2012-01-18 05:21:49 +0000 | [diff] [blame] | 14314 |  | 
|  | 14315 | if (!Diags.empty()) { | 
|  | 14316 | IsConstExpr = false; | 
|  | 14317 | if (Loc) *Loc = Diags[0].first; | 
|  | 14318 | } else if (!IsConstExpr) { | 
|  | 14319 | // FIXME: This shouldn't happen. | 
|  | 14320 | if (Loc) *Loc = getExprLoc(); | 
|  | 14321 | } | 
|  | 14322 |  | 
|  | 14323 | return IsConstExpr; | 
|  | 14324 | } | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14325 |  | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14326 | bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, | 
|  | 14327 | const FunctionDecl *Callee, | 
| George Burgess IV | 177399e | 2017-01-09 04:12:14 +0000 | [diff] [blame] | 14328 | ArrayRef<const Expr*> Args, | 
|  | 14329 | const Expr *This) const { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 14330 | assert(!isValueDependent() && | 
|  | 14331 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 14332 |  | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14333 | Expr::EvalStatus Status; | 
|  | 14334 | EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); | 
| Eric Fiselier | 680e865 | 2019-03-08 22:06:48 +0000 | [diff] [blame] | 14335 | Info.InConstantContext = true; | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14336 |  | 
| George Burgess IV | 177399e | 2017-01-09 04:12:14 +0000 | [diff] [blame] | 14337 | LValue ThisVal; | 
|  | 14338 | const LValue *ThisPtr = nullptr; | 
|  | 14339 | if (This) { | 
|  | 14340 | #ifndef NDEBUG | 
|  | 14341 | auto *MD = dyn_cast<CXXMethodDecl>(Callee); | 
|  | 14342 | assert(MD && "Don't provide `this` for non-methods."); | 
|  | 14343 | assert(!MD->isStatic() && "Don't provide `this` for static methods."); | 
|  | 14344 | #endif | 
| Richard Smith | bb06149 | 2019-10-30 13:32:52 -0700 | [diff] [blame] | 14345 | if (!This->isValueDependent() && | 
|  | 14346 | EvaluateObjectArgument(Info, This, ThisVal) && | 
|  | 14347 | !Info.EvalStatus.HasSideEffects) | 
| George Burgess IV | 177399e | 2017-01-09 04:12:14 +0000 | [diff] [blame] | 14348 | ThisPtr = &ThisVal; | 
| Richard Smith | bb06149 | 2019-10-30 13:32:52 -0700 | [diff] [blame] | 14349 |  | 
|  | 14350 | // Ignore any side-effects from a failed evaluation. This is safe because | 
|  | 14351 | // they can't interfere with any other argument evaluation. | 
|  | 14352 | Info.EvalStatus.HasSideEffects = false; | 
| George Burgess IV | 177399e | 2017-01-09 04:12:14 +0000 | [diff] [blame] | 14353 | } | 
|  | 14354 |  | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14355 | ArgVector ArgValues(Args.size()); | 
|  | 14356 | for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end(); | 
|  | 14357 | I != E; ++I) { | 
| Nick Lewycky | f0202ca | 2014-12-16 06:12:01 +0000 | [diff] [blame] | 14358 | if ((*I)->isValueDependent() || | 
| Richard Smith | bb06149 | 2019-10-30 13:32:52 -0700 | [diff] [blame] | 14359 | !Evaluate(ArgValues[I - Args.begin()], Info, *I) || | 
|  | 14360 | Info.EvalStatus.HasSideEffects) | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14361 | // If evaluation fails, throw away the argument entirely. | 
|  | 14362 | ArgValues[I - Args.begin()] = APValue(); | 
| Richard Smith | bb06149 | 2019-10-30 13:32:52 -0700 | [diff] [blame] | 14363 |  | 
|  | 14364 | // Ignore any side-effects from a failed evaluation. This is safe because | 
|  | 14365 | // they can't interfere with any other argument evaluation. | 
|  | 14366 | Info.EvalStatus.HasSideEffects = false; | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14367 | } | 
|  | 14368 |  | 
| Richard Smith | bb06149 | 2019-10-30 13:32:52 -0700 | [diff] [blame] | 14369 | // Parameter cleanups happen in the caller and are not part of this | 
|  | 14370 | // evaluation. | 
|  | 14371 | Info.discardCleanups(); | 
|  | 14372 | Info.EvalStatus.HasSideEffects = false; | 
|  | 14373 |  | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14374 | // Build fake call to Callee. | 
| George Burgess IV | 177399e | 2017-01-09 04:12:14 +0000 | [diff] [blame] | 14375 | CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr, | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14376 | ArgValues.data()); | 
| Richard Smith | bb06149 | 2019-10-30 13:32:52 -0700 | [diff] [blame] | 14377 | // FIXME: Missing ExprWithCleanups in enable_if conditions? | 
|  | 14378 | FullExpressionRAII Scope(Info); | 
|  | 14379 | return Evaluate(Value, Info, this) && Scope.destroy() && | 
| Richard Smith | 457226e | 2019-09-23 03:48:44 +0000 | [diff] [blame] | 14380 | !Info.EvalStatus.HasSideEffects; | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14381 | } | 
|  | 14382 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14383 | bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, | 
| Dmitri Gribenko | f857950 | 2013-01-12 19:30:44 +0000 | [diff] [blame] | 14384 | SmallVectorImpl< | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14385 | PartialDiagnosticAt> &Diags) { | 
|  | 14386 | // FIXME: It would be useful to check constexpr function templates, but at the | 
|  | 14387 | // moment the constant expression evaluator cannot cope with the non-rigorous | 
|  | 14388 | // ASTs which we build for dependent expressions. | 
|  | 14389 | if (FD->isDependentContext()) | 
|  | 14390 | return true; | 
|  | 14391 |  | 
|  | 14392 | Expr::EvalStatus Status; | 
|  | 14393 | Status.Diag = &Diags; | 
|  | 14394 |  | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 14395 | EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_ConstantExpression); | 
| Fangrui Song | 407659a | 2018-11-30 23:41:18 +0000 | [diff] [blame] | 14396 | Info.InConstantContext = true; | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 14397 | Info.CheckingPotentialConstantExpression = true; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14398 |  | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 14399 | // The constexpr VM attempts to compile all methods to bytecode here. | 
|  | 14400 | if (Info.EnableNewConstInterp) { | 
| Nandor Licker | f584f04 | 2019-11-11 11:13:34 +0000 | [diff] [blame] | 14401 | Info.Ctx.getInterpContext().isPotentialConstantExpr(Info, FD); | 
|  | 14402 | return Diags.empty(); | 
| Nandor Licker | 950b70d | 2019-09-13 09:46:16 +0000 | [diff] [blame] | 14403 | } | 
|  | 14404 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14405 | const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 14406 | const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr; | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14407 |  | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 14408 | // Fabricate an arbitrary expression on the stack and pretend that it | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14409 | // is a temporary being used as the 'this' pointer. | 
|  | 14410 | LValue This; | 
|  | 14411 | ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy); | 
| Akira Hatanaka | 4e2698c | 2018-04-10 05:15:01 +0000 | [diff] [blame] | 14412 | This.set({&VIE, Info.CurrentCall->Index}); | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14413 |  | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14414 | ArrayRef<const Expr*> Args; | 
|  | 14415 |  | 
| Richard Smith | 2e312c8 | 2012-03-03 22:46:17 +0000 | [diff] [blame] | 14416 | APValue Scratch; | 
| Richard Smith | 7525ff6 | 2013-05-09 07:14:00 +0000 | [diff] [blame] | 14417 | if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { | 
|  | 14418 | // Evaluate the call as a constant initializer, to allow the construction | 
|  | 14419 | // of objects of non-literal types. | 
|  | 14420 | Info.setEvaluatingDecl(This.getLValueBase(), Scratch); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 14421 | HandleConstructorCall(&VIE, This, Args, CD, Info, Scratch); | 
|  | 14422 | } else { | 
|  | 14423 | SourceLocation Loc = FD->getLocation(); | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 14424 | HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, | 
| Richard Smith | 52a980a | 2015-08-28 02:43:42 +0000 | [diff] [blame] | 14425 | Args, FD->getBody(), Info, Scratch, nullptr); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 14426 | } | 
| Richard Smith | 253c2a3 | 2012-01-27 01:14:48 +0000 | [diff] [blame] | 14427 |  | 
|  | 14428 | return Diags.empty(); | 
|  | 14429 | } | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14430 |  | 
|  | 14431 | bool Expr::isPotentialConstantExprUnevaluated(Expr *E, | 
|  | 14432 | const FunctionDecl *FD, | 
|  | 14433 | SmallVectorImpl< | 
|  | 14434 | PartialDiagnosticAt> &Diags) { | 
| Dmitri Gribenko | 04323c2 | 2019-05-17 17:16:53 +0000 | [diff] [blame] | 14435 | assert(!E->isValueDependent() && | 
|  | 14436 | "Expression evaluator can't be called on a dependent expression."); | 
|  | 14437 |  | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14438 | Expr::EvalStatus Status; | 
|  | 14439 | Status.Diag = &Diags; | 
|  | 14440 |  | 
|  | 14441 | EvalInfo Info(FD->getASTContext(), Status, | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 14442 | EvalInfo::EM_ConstantExpressionUnevaluated); | 
| Eric Fiselier | 680e865 | 2019-03-08 22:06:48 +0000 | [diff] [blame] | 14443 | Info.InConstantContext = true; | 
| Richard Smith | 045b227 | 2019-09-10 21:24:09 +0000 | [diff] [blame] | 14444 | Info.CheckingPotentialConstantExpression = true; | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14445 |  | 
|  | 14446 | // Fabricate a call stack frame to give the arguments a plausible cover story. | 
|  | 14447 | ArrayRef<const Expr*> Args; | 
|  | 14448 | ArgVector ArgValues(0); | 
| Gauthier Harnisch | 0bb4d46 | 2019-06-15 08:32:56 +0000 | [diff] [blame] | 14449 | bool Success = EvaluateArgs(Args, ArgValues, Info, FD); | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14450 | (void)Success; | 
|  | 14451 | assert(Success && | 
|  | 14452 | "Failed to set up arguments for potential constant evaluation"); | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 14453 | CallStackFrame Frame(Info, SourceLocation(), FD, nullptr, ArgValues.data()); | 
| Nick Lewycky | 35a6ef4 | 2014-01-11 02:50:57 +0000 | [diff] [blame] | 14454 |  | 
|  | 14455 | APValue ResultScratch; | 
|  | 14456 | Evaluate(ResultScratch, Info, E); | 
|  | 14457 | return Diags.empty(); | 
|  | 14458 | } | 
| George Burgess IV | 3e3bb95b | 2015-12-02 21:58:08 +0000 | [diff] [blame] | 14459 |  | 
|  | 14460 | bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, | 
|  | 14461 | unsigned Type) const { | 
|  | 14462 | if (!getType()->isPointerType()) | 
|  | 14463 | return false; | 
|  | 14464 |  | 
|  | 14465 | Expr::EvalStatus Status; | 
|  | 14466 | EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); | 
| George Burgess IV | e376337 | 2016-12-22 02:50:20 +0000 | [diff] [blame] | 14467 | return tryEvaluateBuiltinObjectSize(this, Type, Info, Result); | 
| George Burgess IV | 3e3bb95b | 2015-12-02 21:58:08 +0000 | [diff] [blame] | 14468 | } |