forked from OSchip/llvm-project
Revert "Treat `std::move`, `forward`, and `move_if_noexcept` as builtins."
Revert "Extend support for std::move etc to also cover std::as_const and" Revert "Update test to handle opaque pointers flag flip." It crashes on libcxx tests https://lab.llvm.org/buildbot/#/builders/85/builds/8174 This reverts commitfc30901096
. This reverts commita571f82a50
. This reverts commit64c045e25b
.
This commit is contained in:
parent
709868707c
commit
e75d8b7037
|
@ -252,24 +252,8 @@ Language Selection and Mode Options
|
|||
|
||||
.. option:: -fno-builtin
|
||||
|
||||
Disable special handling and optimizations of well-known library functions,
|
||||
like :c:func:`strlen` and :c:func:`malloc`.
|
||||
|
||||
.. option:: -fno-builtin-<function>
|
||||
|
||||
Disable special handling and optimizations for the specific library function.
|
||||
For example, ``-fno-builtin-strlen`` removes any special handling for the
|
||||
:c:func:`strlen` library function.
|
||||
|
||||
.. option:: -fno-builtin-std-<function>
|
||||
|
||||
Disable special handling and optimizations for the specific C++ standard
|
||||
library function in namespace ``std``. For example,
|
||||
``-fno-builtin-std-move_if_noexcept`` removes any special handling for the
|
||||
:cpp:func:`std::move_if_noexcept` library function.
|
||||
|
||||
For C standard library functions that the C++ standard library also provides
|
||||
in namespace ``std``, use :option:`-fno-builtin-\<function\>` instead.
|
||||
Disable special handling and optimizations of builtin functions like
|
||||
:c:func:`strlen` and :c:func:`malloc`.
|
||||
|
||||
.. option:: -fmath-errno
|
||||
|
||||
|
|
|
@ -230,10 +230,7 @@ C2x Feature Support
|
|||
C++ Language Changes in Clang
|
||||
-----------------------------
|
||||
|
||||
- Improved ``-O0`` code generation for calls to ``std::move``, ``std::forward``,
|
||||
and ``std::move_if_noexcept``. These are now treated as compiler builtins and
|
||||
implemented directly, rather than instantiating the definition from the
|
||||
standard library.
|
||||
- ...
|
||||
|
||||
C++20 Feature Support
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -81,9 +81,7 @@
|
|||
// builtin even if type doesn't match signature, and don't warn if we
|
||||
// can't be sure the type is right
|
||||
// F -> this is a libc/libm function with a '__builtin_' prefix added.
|
||||
// f -> this is a libc/libm function without a '__builtin_' prefix, or with
|
||||
// 'z', a C++ standard library function in namespace std::. This builtin
|
||||
// is disableable by '-fno-builtin-foo' / '-fno-builtin-std-foo'.
|
||||
// f -> this is a libc/libm function without the '__builtin_' prefix.
|
||||
// h -> this function requires a specific header or an explicit declaration.
|
||||
// i -> this is a runtime library implemented function without the
|
||||
// '__builtin_' prefix. It will be implemented in compiler-rt or libgcc.
|
||||
|
@ -103,7 +101,6 @@
|
|||
// V:N: -> requires vectors of at least N bits to be legal
|
||||
// C<N,M_0,...,M_k> -> callback behavior: argument N is called with argument
|
||||
// M_0, ..., M_k as payload
|
||||
// z -> this is a function in (possibly-versioned) namespace std
|
||||
// FIXME: gcc has nonnull
|
||||
|
||||
#if defined(BUILTIN) && !defined(LIBBUILTIN)
|
||||
|
@ -922,7 +919,7 @@ LANGBUILTIN(__exception_info, "v*", "n", ALL_MS_LANGUAGES)
|
|||
LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__GetExceptionInfo, "v*.", "zntu", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_InterlockedAnd8, "ccD*c", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_InterlockedAnd16, "ssD*s", "n", ALL_MS_LANGUAGES)
|
||||
LANGBUILTIN(_InterlockedAnd, "NiNiD*Ni", "n", ALL_MS_LANGUAGES)
|
||||
|
@ -1546,15 +1543,6 @@ LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES)
|
|||
LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
|
||||
// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
|
||||
|
||||
// C++ standard library builtins in namespace 'std'.
|
||||
LIBBUILTIN(addressof, "v*v&", "zfncTh", "memory", CXX_LANG)
|
||||
// Synonym for addressof used internally by libstdc++.
|
||||
LANGBUILTIN(__addressof, "v*v&", "zfncT", CXX_LANG)
|
||||
LIBBUILTIN(as_const, "v&v&", "zfncTh", "utility", CXX_LANG)
|
||||
LIBBUILTIN(forward, "v&v&", "zfncTh", "utility", CXX_LANG)
|
||||
LIBBUILTIN(move, "v&v&", "zfncTh", "utility", CXX_LANG)
|
||||
LIBBUILTIN(move_if_noexcept, "v&v&", "zfncTh", "utility", CXX_LANG)
|
||||
|
||||
// Annotation function
|
||||
BUILTIN(__builtin_annotation, "v.", "tn")
|
||||
|
||||
|
|
|
@ -138,10 +138,6 @@ public:
|
|||
/// Determines whether this builtin is a predefined libc/libm
|
||||
/// function, such as "malloc", where we know the signature a
|
||||
/// priori.
|
||||
/// In C, such functions behave as if they are predeclared,
|
||||
/// possibly with a warning on first use. In Objective-C and C++,
|
||||
/// they do not, but they are recognized as builtins once we see
|
||||
/// a declaration.
|
||||
bool isPredefinedLibFunction(unsigned ID) const {
|
||||
return strchr(getRecord(ID).Attributes, 'f') != nullptr;
|
||||
}
|
||||
|
@ -160,23 +156,6 @@ public:
|
|||
return strchr(getRecord(ID).Attributes, 'i') != nullptr;
|
||||
}
|
||||
|
||||
/// Determines whether this builtin is a C++ standard library function
|
||||
/// that lives in (possibly-versioned) namespace std, possibly a template
|
||||
/// specialization, where the signature is determined by the standard library
|
||||
/// declaration.
|
||||
bool isInStdNamespace(unsigned ID) const {
|
||||
return strchr(getRecord(ID).Attributes, 'z') != nullptr;
|
||||
}
|
||||
|
||||
/// Determines whether this builtin can have its address taken with no
|
||||
/// special action required.
|
||||
bool isDirectlyAddressable(unsigned ID) const {
|
||||
// Most standard library functions can have their addresses taken. C++
|
||||
// standard library functions formally cannot in C++20 onwards, and when
|
||||
// we allow it, we need to ensure we instantiate a definition.
|
||||
return isPredefinedLibFunction(ID) && !isInStdNamespace(ID);
|
||||
}
|
||||
|
||||
/// Determines whether this builtin has custom typechecking.
|
||||
bool hasCustomTypechecking(unsigned ID) const {
|
||||
return strchr(getRecord(ID).Attributes, 't') != nullptr;
|
||||
|
@ -258,6 +237,10 @@ public:
|
|||
private:
|
||||
const Info &getRecord(unsigned ID) const;
|
||||
|
||||
/// Is this builtin supported according to the given language options?
|
||||
bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
|
||||
const LangOptions &LangOpts);
|
||||
|
||||
/// Helper function for isPrintfLike and isScanfLike.
|
||||
bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg,
|
||||
const char *Fmt) const;
|
||||
|
|
|
@ -6586,15 +6586,6 @@ def warn_self_move : Warning<
|
|||
"explicitly moving variable of type %0 to itself">,
|
||||
InGroup<SelfMove>, DefaultIgnore;
|
||||
|
||||
def err_builtin_move_forward_unsupported : Error<
|
||||
"unsupported signature for %q0">;
|
||||
def err_use_of_unaddressable_function : Error<
|
||||
"taking address of non-addressable standard library function">;
|
||||
// FIXME: This should also be in -Wc++23-compat once we have it.
|
||||
def warn_cxx20_compat_use_of_unaddressable_function : Warning<
|
||||
"taking address of non-addressable standard library function "
|
||||
"is incompatible with C++20">, InGroup<CXX20Compat>;
|
||||
|
||||
def warn_redundant_move_on_return : Warning<
|
||||
"redundant move in return statement">,
|
||||
InGroup<RedundantMove>, DefaultIgnore;
|
||||
|
|
|
@ -8127,7 +8127,6 @@ public:
|
|||
bool VisitVarDecl(const Expr *E, const VarDecl *VD);
|
||||
bool VisitUnaryPreIncDec(const UnaryOperator *UO);
|
||||
|
||||
bool VisitCallExpr(const CallExpr *E);
|
||||
bool VisitDeclRefExpr(const DeclRefExpr *E);
|
||||
bool VisitPredefinedExpr(const PredefinedExpr *E) { return Success(E); }
|
||||
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
|
||||
|
@ -8293,20 +8292,6 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
|
|||
return Success(*V, E);
|
||||
}
|
||||
|
||||
bool LValueExprEvaluator::VisitCallExpr(const CallExpr *E) {
|
||||
switch (unsigned BuiltinOp = E->getBuiltinCallee()) {
|
||||
case Builtin::BIas_const:
|
||||
case Builtin::BIforward:
|
||||
case Builtin::BImove:
|
||||
case Builtin::BImove_if_noexcept:
|
||||
if (cast<FunctionDecl>(E->getCalleeDecl())->isConstexpr())
|
||||
return Visit(E->getArg(0));
|
||||
break;
|
||||
}
|
||||
|
||||
return ExprEvaluatorBaseTy::VisitCallExpr(E);
|
||||
}
|
||||
|
||||
bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
|
||||
const MaterializeTemporaryExpr *E) {
|
||||
// Walk through the expression to find the materialized temporary itself.
|
||||
|
@ -9085,8 +9070,6 @@ static bool isOneByteCharacterType(QualType T) {
|
|||
bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
|
||||
unsigned BuiltinOp) {
|
||||
switch (BuiltinOp) {
|
||||
case Builtin::BIaddressof:
|
||||
case Builtin::BI__addressof:
|
||||
case Builtin::BI__builtin_addressof:
|
||||
return evaluateLValue(E->getArg(0), Result);
|
||||
case Builtin::BI__builtin_assume_aligned: {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/Analysis/CodeInjector.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
@ -87,9 +86,6 @@ public:
|
|||
ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,
|
||||
CastKind CK = CK_LValueToRValue);
|
||||
|
||||
/// Create a cast to reference type.
|
||||
CastExpr *makeReferenceCast(const Expr *Arg, QualType Ty);
|
||||
|
||||
/// Create an Objective-C bool literal.
|
||||
ObjCBoolLiteralExpr *makeObjCBool(bool Val);
|
||||
|
||||
|
@ -177,16 +173,6 @@ ImplicitCastExpr *ASTMaker::makeImplicitCast(const Expr *Arg, QualType Ty,
|
|||
/* FPFeatures */ FPOptionsOverride());
|
||||
}
|
||||
|
||||
CastExpr *ASTMaker::makeReferenceCast(const Expr *Arg, QualType Ty) {
|
||||
assert(Ty->isReferenceType());
|
||||
return CXXStaticCastExpr::Create(
|
||||
C, Ty.getNonReferenceType(),
|
||||
Ty->isLValueReferenceType() ? VK_LValue : VK_XValue, CK_NoOp,
|
||||
const_cast<Expr *>(Arg), /*CXXCastPath=*/nullptr,
|
||||
/*Written=*/C.getTrivialTypeSourceInfo(Ty), FPOptionsOverride(),
|
||||
SourceLocation(), SourceLocation(), SourceRange());
|
||||
}
|
||||
|
||||
Expr *ASTMaker::makeIntegralCast(const Expr *Arg, QualType Ty) {
|
||||
if (Arg->getType() == Ty)
|
||||
return const_cast<Expr*>(Arg);
|
||||
|
@ -310,22 +296,6 @@ static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
|
|||
/*FPFeatures=*/FPOptionsOverride());
|
||||
}
|
||||
|
||||
/// Create a fake body for 'std::move' or 'std::forward'. This is just:
|
||||
///
|
||||
/// \code
|
||||
/// return static_cast<return_type>(param);
|
||||
/// \endcode
|
||||
static Stmt *create_std_move_forward(ASTContext &C, const FunctionDecl *D) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "Generating body for std::move / std::forward\n");
|
||||
|
||||
ASTMaker M(C);
|
||||
|
||||
QualType ReturnType = D->getType()->castAs<FunctionType>()->getReturnType();
|
||||
Expr *Param = M.makeDeclRefExpr(D->getParamDecl(0));
|
||||
Expr *Cast = M.makeReferenceCast(Param, ReturnType);
|
||||
return M.makeReturn(Cast);
|
||||
}
|
||||
|
||||
/// Create a fake body for std::call_once.
|
||||
/// Emulates the following function body:
|
||||
///
|
||||
|
@ -711,20 +681,8 @@ Stmt *BodyFarm::getBody(const FunctionDecl *D) {
|
|||
|
||||
FunctionFarmer FF;
|
||||
|
||||
if (unsigned BuiltinID = D->getBuiltinID()) {
|
||||
switch (BuiltinID) {
|
||||
case Builtin::BIas_const:
|
||||
case Builtin::BIforward:
|
||||
case Builtin::BImove:
|
||||
case Builtin::BImove_if_noexcept:
|
||||
FF = create_std_move_forward;
|
||||
break;
|
||||
default:
|
||||
FF = nullptr;
|
||||
break;
|
||||
}
|
||||
} else if (Name.startswith("OSAtomicCompareAndSwap") ||
|
||||
Name.startswith("objc_atomicCompareAndSwap")) {
|
||||
if (Name.startswith("OSAtomicCompareAndSwap") ||
|
||||
Name.startswith("objc_atomicCompareAndSwap")) {
|
||||
FF = create_OSAtomicCompareAndSwap;
|
||||
} else if (Name == "call_once" && D->getDeclContext()->isStdNamespace()) {
|
||||
FF = create_call_once;
|
||||
|
|
|
@ -48,22 +48,18 @@ void Builtin::Context::InitializeTarget(const TargetInfo &Target,
|
|||
}
|
||||
|
||||
bool Builtin::Context::isBuiltinFunc(llvm::StringRef FuncName) {
|
||||
bool InStdNamespace = FuncName.consume_front("std-");
|
||||
for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin;
|
||||
++i) {
|
||||
if (FuncName.equals(BuiltinInfo[i].Name) &&
|
||||
(bool)strchr(BuiltinInfo[i].Attributes, 'z') == InStdNamespace)
|
||||
for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i)
|
||||
if (FuncName.equals(BuiltinInfo[i].Name))
|
||||
return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Is this builtin supported according to the given language options?
|
||||
static bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
|
||||
const LangOptions &LangOpts) {
|
||||
bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
|
||||
const LangOptions &LangOpts) {
|
||||
bool BuiltinsUnsupported =
|
||||
LangOpts.NoBuiltin && strchr(BuiltinInfo.Attributes, 'f') != nullptr;
|
||||
(LangOpts.NoBuiltin || LangOpts.isNoBuiltinFunc(BuiltinInfo.Name)) &&
|
||||
strchr(BuiltinInfo.Attributes, 'f');
|
||||
bool CorBuiltinsUnsupported =
|
||||
!LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG);
|
||||
bool MathBuiltinsUnsupported =
|
||||
|
@ -115,19 +111,6 @@ void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
|
|||
for (unsigned i = 0, e = AuxTSRecords.size(); i != e; ++i)
|
||||
Table.get(AuxTSRecords[i].Name)
|
||||
.setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size());
|
||||
|
||||
// Step #4: Unregister any builtins specified by -fno-builtin-foo.
|
||||
for (llvm::StringRef Name : LangOpts.NoBuiltinFuncs) {
|
||||
bool InStdNamespace = Name.consume_front("std-");
|
||||
auto NameIt = Table.find(Name);
|
||||
if (NameIt != Table.end()) {
|
||||
unsigned ID = NameIt->second->getBuiltinID();
|
||||
if (ID != Builtin::NotBuiltin && isPredefinedLibFunction(ID) &&
|
||||
isInStdNamespace(ID) == InStdNamespace) {
|
||||
Table.get(Name).setBuiltinID(Builtin::NotBuiltin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const {
|
||||
|
@ -207,7 +190,8 @@ bool Builtin::Context::performsCallback(unsigned ID,
|
|||
}
|
||||
|
||||
bool Builtin::Context::canBeRedeclared(unsigned ID) const {
|
||||
return ID == Builtin::NotBuiltin || ID == Builtin::BI__va_start ||
|
||||
(!hasReferenceArgsOrResult(ID) && !hasCustomTypechecking(ID)) ||
|
||||
isInStdNamespace(ID);
|
||||
return ID == Builtin::NotBuiltin ||
|
||||
ID == Builtin::BI__va_start ||
|
||||
(!hasReferenceArgsOrResult(ID) &&
|
||||
!hasCustomTypechecking(ID));
|
||||
}
|
||||
|
|
|
@ -4566,8 +4566,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
|||
|
||||
return RValue::get(Carry);
|
||||
}
|
||||
case Builtin::BIaddressof:
|
||||
case Builtin::BI__addressof:
|
||||
case Builtin::BI__builtin_addressof:
|
||||
return RValue::get(EmitLValue(E->getArg(0)).getPointer(*this));
|
||||
case Builtin::BI__builtin_function_start:
|
||||
|
@ -4727,12 +4725,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
|||
}
|
||||
break;
|
||||
|
||||
// C++ std:: builtins.
|
||||
case Builtin::BImove:
|
||||
case Builtin::BImove_if_noexcept:
|
||||
case Builtin::BIforward:
|
||||
case Builtin::BIas_const:
|
||||
return RValue::get(EmitLValue(E->getArg(0)).getPointer(*this));
|
||||
case Builtin::BI__GetExceptionInfo: {
|
||||
if (llvm::GlobalVariable *GV =
|
||||
CGM.getCXXABI().getThrowInfo(FD->getParamDecl(0)->getType()))
|
||||
|
|
|
@ -1805,8 +1805,6 @@ void CodeGenModule::getDefaultFunctionAttributes(StringRef Name,
|
|||
|
||||
if (AttrOnCallSite) {
|
||||
// Attributes that should go on the call site only.
|
||||
// FIXME: Look for 'BuiltinAttr' on the function rather than re-checking
|
||||
// the -fno-builtin-foo list.
|
||||
if (!CodeGenOpts.SimplifyLibCalls || LangOpts.isNoBuiltinFunc(Name))
|
||||
FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
|
||||
if (!CodeGenOpts.TrapFuncName.empty())
|
||||
|
|
|
@ -2130,32 +2130,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
|
|||
|
||||
TheCall->setType(Context.VoidPtrTy);
|
||||
break;
|
||||
case Builtin::BIaddressof:
|
||||
case Builtin::BI__addressof:
|
||||
case Builtin::BIforward:
|
||||
case Builtin::BImove:
|
||||
case Builtin::BImove_if_noexcept:
|
||||
case Builtin::BIas_const: {
|
||||
// These are all expected to be of the form
|
||||
// T &/&&/* f(U &/&&)
|
||||
// where T and U only differ in qualification.
|
||||
if (checkArgCount(*this, TheCall, 1))
|
||||
return ExprError();
|
||||
QualType Param = FDecl->getParamDecl(0)->getType();
|
||||
QualType Result = FDecl->getReturnType();
|
||||
bool ReturnsPointer = BuiltinID == Builtin::BIaddressof ||
|
||||
BuiltinID == Builtin::BI__addressof;
|
||||
if (!(Param->isReferenceType() &&
|
||||
(ReturnsPointer ? Result->isPointerType()
|
||||
: Result->isReferenceType()) &&
|
||||
Context.hasSameUnqualifiedType(Param->getPointeeType(),
|
||||
Result->getPointeeType()))) {
|
||||
Diag(TheCall->getBeginLoc(), diag::err_builtin_move_forward_unsupported)
|
||||
<< FDecl;
|
||||
return ExprError();
|
||||
}
|
||||
break;
|
||||
}
|
||||
// OpenCL v2.0, s6.13.16 - Pipe functions
|
||||
case Builtin::BIread_pipe:
|
||||
case Builtin::BIwrite_pipe:
|
||||
|
|
|
@ -9269,32 +9269,6 @@ static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) {
|
|||
return S;
|
||||
}
|
||||
|
||||
/// Determine whether a declaration matches a known function in namespace std.
|
||||
static bool isStdBuiltin(ASTContext &Ctx, FunctionDecl *FD,
|
||||
unsigned BuiltinID) {
|
||||
switch (BuiltinID) {
|
||||
case Builtin::BI__GetExceptionInfo:
|
||||
// No type checking whatsoever.
|
||||
return Ctx.getTargetInfo().getCXXABI().isMicrosoft();
|
||||
|
||||
case Builtin::BIaddressof:
|
||||
case Builtin::BI__addressof:
|
||||
case Builtin::BIforward:
|
||||
case Builtin::BImove:
|
||||
case Builtin::BImove_if_noexcept:
|
||||
case Builtin::BIas_const: {
|
||||
// Ensure that we don't treat the algorithm
|
||||
// OutputIt std::move(InputIt, InputIt, OutputIt)
|
||||
// as the builtin std::move.
|
||||
const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
|
||||
return FPT->getNumParams() == 1 && !FPT->isVariadic();
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NamedDecl*
|
||||
Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
TypeSourceInfo *TInfo, LookupResult &Previous,
|
||||
|
@ -10147,30 +10121,28 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
|
||||
// If this is the first declaration of a library builtin function, add
|
||||
// attributes as appropriate.
|
||||
if (!D.isRedeclaration()) {
|
||||
if (!D.isRedeclaration() &&
|
||||
NewFD->getDeclContext()->getRedeclContext()->isFileContext()) {
|
||||
if (IdentifierInfo *II = Previous.getLookupName().getAsIdentifierInfo()) {
|
||||
if (unsigned BuiltinID = II->getBuiltinID()) {
|
||||
bool InStdNamespace = Context.BuiltinInfo.isInStdNamespace(BuiltinID);
|
||||
if (!InStdNamespace &&
|
||||
NewFD->getDeclContext()->getRedeclContext()->isFileContext()) {
|
||||
if (NewFD->getLanguageLinkage() == CLanguageLinkage) {
|
||||
// Validate the type matches unless this builtin is specified as
|
||||
// matching regardless of its declared type.
|
||||
if (Context.BuiltinInfo.allowTypeMismatch(BuiltinID)) {
|
||||
NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
|
||||
} else {
|
||||
ASTContext::GetBuiltinTypeError Error;
|
||||
LookupNecessaryTypesForBuiltin(S, BuiltinID);
|
||||
QualType BuiltinType = Context.GetBuiltinType(BuiltinID, Error);
|
||||
if (NewFD->getLanguageLinkage() == CLanguageLinkage) {
|
||||
// Validate the type matches unless this builtin is specified as
|
||||
// matching regardless of its declared type.
|
||||
if (Context.BuiltinInfo.allowTypeMismatch(BuiltinID)) {
|
||||
NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
|
||||
} else {
|
||||
ASTContext::GetBuiltinTypeError Error;
|
||||
LookupNecessaryTypesForBuiltin(S, BuiltinID);
|
||||
QualType BuiltinType = Context.GetBuiltinType(BuiltinID, Error);
|
||||
|
||||
if (!Error && !BuiltinType.isNull() &&
|
||||
Context.hasSameFunctionTypeIgnoringExceptionSpec(
|
||||
NewFD->getType(), BuiltinType))
|
||||
NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
|
||||
}
|
||||
if (!Error && !BuiltinType.isNull() &&
|
||||
Context.hasSameFunctionTypeIgnoringExceptionSpec(
|
||||
NewFD->getType(), BuiltinType))
|
||||
NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
|
||||
}
|
||||
} else if (InStdNamespace && NewFD->isInStdNamespace() &&
|
||||
isStdBuiltin(Context, NewFD, BuiltinID)) {
|
||||
} else if (BuiltinID == Builtin::BI__GetExceptionInfo &&
|
||||
Context.getTargetInfo().getCXXABI().isMicrosoft()) {
|
||||
// FIXME: We should consider this a builtin only in the std namespace.
|
||||
NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3395,7 +3395,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
|
|||
|
||||
case Decl::Function: {
|
||||
if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) {
|
||||
if (!Context.BuiltinInfo.isDirectlyAddressable(BID)) {
|
||||
if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
|
||||
type = Context.BuiltinFnTy;
|
||||
valueKind = VK_PRValue;
|
||||
break;
|
||||
|
@ -20528,8 +20528,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
|
|||
auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
|
||||
if (DRE) {
|
||||
auto *FD = cast<FunctionDecl>(DRE->getDecl());
|
||||
unsigned BuiltinID = FD->getBuiltinID();
|
||||
if (BuiltinID == Builtin::BI__noop) {
|
||||
if (FD->getBuiltinID() == Builtin::BI__noop) {
|
||||
E = ImpCastExprToType(E, Context.getPointerType(FD->getType()),
|
||||
CK_BuiltinFnToFnPtr)
|
||||
.get();
|
||||
|
@ -20537,36 +20536,6 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
|
|||
VK_PRValue, SourceLocation(),
|
||||
FPOptionsOverride());
|
||||
}
|
||||
|
||||
if (Context.BuiltinInfo.isInStdNamespace(BuiltinID)) {
|
||||
// Any use of these other than a direct call is ill-formed as of C++20,
|
||||
// because they are not addressable functions. In earlier language
|
||||
// modes, warn and force an instantiation of the real body.
|
||||
Diag(E->getBeginLoc(),
|
||||
getLangOpts().CPlusPlus20
|
||||
? diag::err_use_of_unaddressable_function
|
||||
: diag::warn_cxx20_compat_use_of_unaddressable_function);
|
||||
if (FD->isImplicitlyInstantiable()) {
|
||||
// Require a definition here because a normal attempt at
|
||||
// instantiation for a builtin will be ignored, and we won't try
|
||||
// again later. We assume that the definition of the template
|
||||
// precedes this use.
|
||||
InstantiateFunctionDefinition(E->getBeginLoc(), FD,
|
||||
/*Recursive=*/false,
|
||||
/*DefinitionRequired=*/true,
|
||||
/*AtEndOfTU=*/false);
|
||||
}
|
||||
// Produce a properly-typed reference to the function.
|
||||
CXXScopeSpec SS;
|
||||
SS.Adopt(DRE->getQualifierLoc());
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
DRE->copyTemplateArgumentsInto(TemplateArgs);
|
||||
return BuildDeclRefExpr(
|
||||
FD, FD->getType(), VK_LValue, DRE->getNameInfo(),
|
||||
DRE->hasQualifier() ? &SS : nullptr, DRE->getFoundDecl(),
|
||||
DRE->getTemplateKeywordLoc(),
|
||||
DRE->hasExplicitTemplateArgs() ? &TemplateArgs : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Diag(E->getBeginLoc(), diag::err_builtin_fn_use);
|
||||
|
|
|
@ -4236,14 +4236,6 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
|
|||
return ExprError();
|
||||
|
||||
From = FixOverloadedFunctionReference(From, Found, Fn);
|
||||
|
||||
// We might get back another placeholder expression if we resolved to a
|
||||
// builtin.
|
||||
ExprResult Checked = CheckPlaceholderExpr(From);
|
||||
if (Checked.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
From = Checked.get();
|
||||
FromType = From->getType();
|
||||
}
|
||||
|
||||
|
|
|
@ -8215,10 +8215,6 @@ ExprResult InitializationSequence::Perform(Sema &S,
|
|||
CurInit = S.FixOverloadedFunctionReference(CurInit,
|
||||
Step->Function.FoundDecl,
|
||||
Step->Function.Function);
|
||||
// We might get back another placeholder expression if we resolved to a
|
||||
// builtin.
|
||||
if (!CurInit.isInvalid())
|
||||
CurInit = S.CheckPlaceholderExpr(CurInit.get());
|
||||
break;
|
||||
|
||||
case SK_CastDerivedToBasePRValue:
|
||||
|
|
|
@ -1747,6 +1747,13 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
|
|||
"Non-address-of operator for overloaded function expression");
|
||||
FromType = S.Context.getPointerType(FromType);
|
||||
}
|
||||
|
||||
// Check that we've computed the proper type after overload resolution.
|
||||
// FIXME: FixOverloadedFunctionReference has side-effects; we shouldn't
|
||||
// be calling it from within an NDEBUG block.
|
||||
assert(S.Context.hasSameType(
|
||||
FromType,
|
||||
S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -15181,9 +15188,10 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
|
|||
if (SubExpr == UnOp->getSubExpr())
|
||||
return UnOp;
|
||||
|
||||
// FIXME: This can't currently fail, but in principle it could.
|
||||
return CreateBuiltinUnaryOp(UnOp->getOperatorLoc(), UO_AddrOf, SubExpr)
|
||||
.get();
|
||||
return UnaryOperator::Create(
|
||||
Context, SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()),
|
||||
VK_PRValue, OK_Ordinary, UnOp->getOperatorLoc(), false,
|
||||
CurFPFeatureOverrides());
|
||||
}
|
||||
|
||||
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
|
||||
|
@ -15194,20 +15202,10 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
|
|||
TemplateArgs = &TemplateArgsBuffer;
|
||||
}
|
||||
|
||||
QualType Type = Fn->getType();
|
||||
ExprValueKind ValueKind = getLangOpts().CPlusPlus ? VK_LValue : VK_PRValue;
|
||||
|
||||
// FIXME: Duplicated from BuildDeclarationNameExpr.
|
||||
if (unsigned BID = Fn->getBuiltinID()) {
|
||||
if (!Context.BuiltinInfo.isDirectlyAddressable(BID)) {
|
||||
Type = Context.BuiltinFnTy;
|
||||
ValueKind = VK_PRValue;
|
||||
}
|
||||
}
|
||||
|
||||
DeclRefExpr *DRE = BuildDeclRefExpr(
|
||||
Fn, Type, ValueKind, ULE->getNameInfo(), ULE->getQualifierLoc(),
|
||||
Found.getDecl(), ULE->getTemplateKeywordLoc(), TemplateArgs);
|
||||
DeclRefExpr *DRE =
|
||||
BuildDeclRefExpr(Fn, Fn->getType(), VK_LValue, ULE->getNameInfo(),
|
||||
ULE->getQualifierLoc(), Found.getDecl(),
|
||||
ULE->getTemplateKeywordLoc(), TemplateArgs);
|
||||
DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1);
|
||||
return DRE;
|
||||
}
|
||||
|
|
|
@ -4771,12 +4771,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
|||
if (TSK == TSK_ExplicitSpecialization)
|
||||
return;
|
||||
|
||||
// Never implicitly instantiate a builtin; we don't actually need a function
|
||||
// body.
|
||||
if (Function->getBuiltinID() && TSK == TSK_ImplicitInstantiation &&
|
||||
!DefinitionRequired)
|
||||
return;
|
||||
|
||||
// Don't instantiate a definition if we already have one.
|
||||
const FunctionDecl *ExistingDefn = nullptr;
|
||||
if (Function->isDefined(ExistingDefn,
|
||||
|
|
|
@ -379,7 +379,7 @@ void func_addressof() {
|
|||
const char *c;
|
||||
std::string s;
|
||||
c = s.c_str();
|
||||
(void)addressof(s);
|
||||
addressof(s);
|
||||
consume(c); // no-warning
|
||||
}
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ void reinitializationTest(int i) {
|
|||
A a;
|
||||
if (i == 1) { // peaceful-note 2 {{'i' is not equal to 1}}
|
||||
// peaceful-note@-1 2 {{Taking false branch}}
|
||||
(void)std::move(a);
|
||||
std::move(a);
|
||||
}
|
||||
if (i == 2) { // peaceful-note 2 {{'i' is not equal to 2}}
|
||||
// peaceful-note@-1 2 {{Taking false branch}}
|
||||
|
@ -494,7 +494,7 @@ void templateArgIsNotUseTest() {
|
|||
// Moves of global variables are not reported.
|
||||
A global_a;
|
||||
void globalVariablesTest() {
|
||||
(void)std::move(global_a);
|
||||
std::move(global_a);
|
||||
global_a.foo(); // no-warning
|
||||
}
|
||||
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - -std=c++17 %s | FileCheck %s --implicit-check-not=@_ZSt4move
|
||||
|
||||
namespace std {
|
||||
template<typename T> constexpr T &&move(T &val) { return static_cast<T&&>(val); }
|
||||
template<typename T> constexpr T &&move_if_noexcept(T &val);
|
||||
template<typename T> constexpr T &&forward(T &val);
|
||||
template<typename T> constexpr const T &as_const(T &val);
|
||||
|
||||
// Not the builtin.
|
||||
template<typename T, typename U> T move(U source, U source_end, T dest);
|
||||
}
|
||||
|
||||
class T {};
|
||||
extern "C" void take(T &&);
|
||||
extern "C" void take_lval(const T &);
|
||||
|
||||
T a;
|
||||
|
||||
// Check emission of a constant-evaluated call.
|
||||
// CHECK-DAG: @move_a = constant ptr @a
|
||||
T &&move_a = std::move(a);
|
||||
// CHECK-DAG: @move_if_noexcept_a = constant ptr @a
|
||||
T &&move_if_noexcept_a = std::move_if_noexcept(a);
|
||||
// CHECK-DAG: @forward_a = constant ptr @a
|
||||
T &forward_a = std::forward<T&>(a);
|
||||
|
||||
// Check emission of a non-constant call.
|
||||
// CHECK-LABEL: define {{.*}} void @test
|
||||
extern "C" void test(T &t) {
|
||||
// CHECK: store ptr %{{.*}}, ptr %[[T_REF:[^,]*]]
|
||||
// CHECK: %0 = load ptr, ptr %[[T_REF]]
|
||||
// CHECK: call void @take(ptr {{.*}} %0)
|
||||
take(std::move(t));
|
||||
// CHECK: %1 = load ptr, ptr %[[T_REF]]
|
||||
// CHECK: call void @take(ptr {{.*}} %1)
|
||||
take(std::move_if_noexcept(t));
|
||||
// CHECK: %2 = load ptr, ptr %[[T_REF]]
|
||||
// CHECK: call void @take(ptr {{.*}} %2)
|
||||
take(std::forward<T&&>(t));
|
||||
// CHECK: %3 = load ptr, ptr %[[T_REF]]
|
||||
// CHECK: call void @take_lval(ptr {{.*}} %3)
|
||||
take_lval(std::as_const<T&&>(t));
|
||||
|
||||
// CHECK: call {{.*}} @_ZSt4moveI1TS0_ET_T0_S2_S1_
|
||||
std::move(t, t, t);
|
||||
}
|
||||
|
||||
// CHECK: declare {{.*}} @_ZSt4moveI1TS0_ET_T0_S2_S1_
|
||||
|
||||
// Check that we instantiate and emit if the address is taken.
|
||||
// CHECK-LABEL: define {{.*}} @use_address
|
||||
extern "C" void *use_address() {
|
||||
// CHECK: ret {{.*}} @_ZSt4moveIiEOT_RS0_
|
||||
return (void*)&std::move<int>;
|
||||
}
|
||||
|
||||
// CHECK: define {{.*}} ptr @_ZSt4moveIiEOT_RS0_(ptr
|
|
@ -30,24 +30,6 @@ S *addressof(bool b, S &s, S &t) {
|
|||
return __builtin_addressof(b ? s : t);
|
||||
}
|
||||
|
||||
namespace std { template<typename T> T *addressof(T &); }
|
||||
|
||||
// CHECK: define {{.*}} @_Z13std_addressofbR1SS0_(
|
||||
S *std_addressof(bool b, S &s, S &t) {
|
||||
// CHECK: %[[LVALUE:.*]] = phi
|
||||
// CHECK: ret {{.*}}* %[[LVALUE]]
|
||||
return std::addressof(b ? s : t);
|
||||
}
|
||||
|
||||
namespace std { template<typename T> T *__addressof(T &); }
|
||||
|
||||
// CHECK: define {{.*}} @_Z15std___addressofbR1SS0_(
|
||||
S *std___addressof(bool b, S &s, S &t) {
|
||||
// CHECK: %[[LVALUE:.*]] = phi
|
||||
// CHECK: ret {{.*}}* %[[LVALUE]]
|
||||
return std::__addressof(b ? s : t);
|
||||
}
|
||||
|
||||
extern "C" int __builtin_abs(int); // #1
|
||||
long __builtin_abs(long); // #2
|
||||
extern "C" int __builtin_abs(int); // #3
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions | FileCheck %s
|
||||
// RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions -fms-extensions -DSTD | FileCheck %s
|
||||
|
||||
// CHECK-DAG: @"??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
|
||||
// CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"??0Y@@QAE@ABU0@@Z" to i8*) }, section ".xdata", comdat
|
||||
|
@ -133,10 +134,15 @@ void h() {
|
|||
throw nullptr;
|
||||
}
|
||||
|
||||
#ifdef STD
|
||||
namespace std {
|
||||
template <typename T>
|
||||
void *__GetExceptionInfo(T);
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
void *__GetExceptionInfo(T);
|
||||
#endif
|
||||
using namespace std;
|
||||
|
||||
void *GetExceptionInfo_test0() {
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
// RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=builtin
|
||||
// RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=nobuiltin -fno-builtin
|
||||
// RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=nobuiltin -fno-builtin-std-move -fno-builtin-std-move_if_noexcept -fno-builtin-std-forward
|
||||
// RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=nobuiltin -ffreestanding
|
||||
// expected-no-diagnostics
|
||||
|
||||
int nobuiltin;
|
||||
|
||||
namespace std {
|
||||
template<typename T> constexpr T &&move(T &x) { return (T&&)nobuiltin; }
|
||||
template<typename T> constexpr T &&move_if_noexcept(T &x) { return (T&&)nobuiltin; }
|
||||
template<typename T> constexpr T &&forward(T &x) { return (T&&)nobuiltin; }
|
||||
}
|
||||
|
||||
template<typename T> constexpr T *addr(T &&r) { return &r; }
|
||||
|
||||
int builtin;
|
||||
static_assert(addr(std::move(builtin)) == &BUILTIN);
|
||||
static_assert(addr(std::move_if_noexcept(builtin)) == &BUILTIN);
|
||||
static_assert(addr(std::forward(builtin)) == &BUILTIN);
|
|
@ -1,126 +0,0 @@
|
|||
// RUN: %clang_cc1 -std=c++17 -verify %s
|
||||
// RUN: %clang_cc1 -std=c++17 -verify %s -DNO_CONSTEXPR
|
||||
// RUN: %clang_cc1 -std=c++20 -verify %s
|
||||
|
||||
namespace std {
|
||||
#ifndef NO_CONSTEXPR
|
||||
#define CONSTEXPR constexpr
|
||||
#else
|
||||
#define CONSTEXPR
|
||||
#endif
|
||||
|
||||
template<typename T> CONSTEXPR T &&move(T &x) {
|
||||
static_assert(T::moveable, "instantiated move"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'C'}}
|
||||
return static_cast<T&&>(x);
|
||||
}
|
||||
|
||||
// Unrelated move functions are not the builtin.
|
||||
template<typename T> CONSTEXPR int move(T, T) { return 5; }
|
||||
|
||||
template<typename T, bool Rref> struct ref { using type = T&; };
|
||||
template<typename T> struct ref<T, true> { using type = T&&; };
|
||||
|
||||
template<typename T> CONSTEXPR auto move_if_noexcept(T &x) -> typename ref<T, noexcept(T(static_cast<T&&>(x)))>::type {
|
||||
static_assert(T::moveable, "instantiated move_if_noexcept"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
return static_cast<typename ref<T, noexcept(T(static_cast<T&&>(x)))>::type>(x);
|
||||
}
|
||||
|
||||
template<typename T> struct remove_reference { using type = T; };
|
||||
template<typename T> struct remove_reference<T&> { using type = T; };
|
||||
template<typename T> struct remove_reference<T&&> { using type = T; };
|
||||
|
||||
template<typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &x) {
|
||||
static_assert(T::moveable, "instantiated forward"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'C'}}
|
||||
return static_cast<T&&>(x);
|
||||
}
|
||||
|
||||
template<typename T> CONSTEXPR const T &as_const(T &x) {
|
||||
static_assert(T::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename T> CONSTEXPR T *addressof(T &x) {
|
||||
static_assert(T::moveable, "instantiated addressof"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
return __builtin_addressof(x);
|
||||
}
|
||||
|
||||
template<typename T> CONSTEXPR T *__addressof(T &x) {
|
||||
static_assert(T::moveable, "instantiated __addressof"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
return __builtin_addressof(x);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this doesn't have a 'moveable' member. Instantiation of the above
|
||||
// functions will fail if it's attempted.
|
||||
struct A {};
|
||||
constexpr bool f(A a) { // #f
|
||||
A &&move = std::move(a); // #call
|
||||
A &&move_if_noexcept = std::move_if_noexcept(a);
|
||||
A &&forward1 = std::forward<A>(a);
|
||||
A &forward2 = std::forward<A&>(a);
|
||||
const A &as_const = std::as_const(a);
|
||||
A *addressof = std::addressof(a);
|
||||
A *addressof2 = std::__addressof(a);
|
||||
return &move == &a && &move_if_noexcept == &a &&
|
||||
&forward1 == &a && &forward2 == &a &&
|
||||
&as_const == &a && addressof == &a &&
|
||||
addressof2 == &a && std::move(a, a) == 5;
|
||||
}
|
||||
|
||||
#ifndef NO_CONSTEXPR
|
||||
static_assert(f({}), "should be constexpr");
|
||||
#else
|
||||
// expected-error@#f {{never produces a constant expression}}
|
||||
// expected-note@#call {{}}
|
||||
#endif
|
||||
|
||||
struct B {};
|
||||
B &&(*pMove)(B&) = std::move; // #1 expected-note {{instantiation of}}
|
||||
B &&(*pMoveIfNoexcept)(B&) = &std::move_if_noexcept; // #2 expected-note {{instantiation of}}
|
||||
B &&(*pForward)(B&) = &std::forward<B>; // #3 expected-note {{instantiation of}}
|
||||
const B &(*pAsConst)(B&) = &std::as_const; // #4 expected-note {{instantiation of}}
|
||||
B *(*pAddressof)(B&) = &std::addressof; // #5 expected-note {{instantiation of}}
|
||||
B *(*pUnderUnderAddressof)(B&) = &std::__addressof; // #6 expected-note {{instantiation of}}
|
||||
int (*pUnrelatedMove)(B, B) = std::move;
|
||||
|
||||
struct C {};
|
||||
C &&(&rMove)(C&) = std::move; // #7 expected-note {{instantiation of}}
|
||||
C &&(&rForward)(C&) = std::forward<C>; // #8 expected-note {{instantiation of}}
|
||||
int (&rUnrelatedMove)(B, B) = std::move;
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
// expected-warning@#1 {{non-addressable}}
|
||||
// expected-warning@#2 {{non-addressable}}
|
||||
// expected-warning@#3 {{non-addressable}}
|
||||
// expected-warning@#4 {{non-addressable}}
|
||||
// expected-warning@#5 {{non-addressable}}
|
||||
// expected-warning@#6 {{non-addressable}}
|
||||
// expected-warning@#7 {{non-addressable}}
|
||||
// expected-warning@#8 {{non-addressable}}
|
||||
#else
|
||||
// expected-error@#1 {{non-addressable}}
|
||||
// expected-error@#2 {{non-addressable}}
|
||||
// expected-error@#3 {{non-addressable}}
|
||||
// expected-error@#4 {{non-addressable}}
|
||||
// expected-error@#5 {{non-addressable}}
|
||||
// expected-error@#6 {{non-addressable}}
|
||||
// expected-error@#7 {{non-addressable}}
|
||||
// expected-error@#8 {{non-addressable}}
|
||||
#endif
|
||||
|
||||
void attribute_const() {
|
||||
int n;
|
||||
std::move(n); // expected-warning {{ignoring return value}}
|
||||
std::move_if_noexcept(n); // expected-warning {{ignoring return value}}
|
||||
std::forward<int>(n); // expected-warning {{ignoring return value}}
|
||||
std::addressof(n); // expected-warning {{ignoring return value}}
|
||||
std::__addressof(n); // expected-warning {{ignoring return value}}
|
||||
std::as_const(n); // expected-warning {{ignoring return value}}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<typename T> int move(T);
|
||||
}
|
||||
int bad_signature = std::move(0); // expected-error {{unsupported signature for 'std::move<int>'}}
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
namespace std {
|
||||
|
||||
int &&move(auto &&a) { return a; }
|
||||
void move(auto &&a) {}
|
||||
|
||||
int &&forward(auto &a) { return a; }
|
||||
void forward(auto &a) {}
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
@ -16,8 +16,8 @@ using namespace std;
|
|||
|
||||
void f() {
|
||||
int i = 0;
|
||||
(void)move(i); // expected-warning {{unqualified call to std::move}}
|
||||
// CHECK: {{^}} (void)std::move
|
||||
(void)forward(i); // expected-warning {{unqualified call to std::forward}}
|
||||
// CHECK: {{^}} (void)std::forward
|
||||
move(i); // expected-warning {{unqualified call to std::move}}
|
||||
// CHECK: {{^}} std::
|
||||
forward(i); // expected-warning {{unqualified call to std::forward}}
|
||||
// CHECK: {{^}} std::
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -Wall -std=c++11 %s -Wno-unused-value
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -Wall -std=c++11 %s
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename T>
|
||||
void dummy(T &&) {}
|
||||
template <typename T>
|
||||
T &&move(T &&x) { return x; }
|
||||
void move(T &&) {}
|
||||
template <typename T, typename U>
|
||||
void move(T &&, U &&) {}
|
||||
|
||||
inline namespace __1 {
|
||||
template <typename T>
|
||||
T &forward(T &x) { return x; }
|
||||
void forward(T &) {}
|
||||
} // namespace __1
|
||||
|
||||
struct foo {};
|
||||
|
|
|
@ -953,12 +953,12 @@ void test6() {
|
|||
namespace std {
|
||||
void move();
|
||||
template<class T>
|
||||
T &&move(T&);
|
||||
void move(T&&);
|
||||
|
||||
namespace __1 {
|
||||
void move();
|
||||
template<class T>
|
||||
T &&move(T&);
|
||||
void move(T&&);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -971,7 +971,7 @@ namespace PR18260 {
|
|||
void test() {
|
||||
x.move();
|
||||
std::move();
|
||||
std::move(x); // expected-warning {{ignoring return value}}
|
||||
std::move(x);
|
||||
std::__1::move();
|
||||
std::__1::move(x);
|
||||
}
|
||||
|
|
|
@ -1444,7 +1444,7 @@ TEST(ExprMutationAnalyzerTest, UnevaluatedContext) {
|
|||
TEST(ExprMutationAnalyzerTest, ReproduceFailureMinimal) {
|
||||
const std::string Reproducer =
|
||||
"namespace std {"
|
||||
"template <class T> T &forward(T &A) { return static_cast<T&&>(A); }"
|
||||
"template <class T> T forward(T & A) { return static_cast<T&&>(A); }"
|
||||
"template <class T> struct __bind {"
|
||||
" T f;"
|
||||
" template <class V> __bind(T v, V &&) : f(forward(v)) {}"
|
||||
|
|
Loading…
Reference in New Issue