[clang] 98d911e - Revert "Treat `std::move`, `forward`, etc. as builtins."
David Tenty via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 20 16:15:11 PDT 2022
Author: David Tenty
Date: 2022-04-20T19:14:37-04:00
New Revision: 98d911e01f3ac62a9f78850b4209effcf2f54c91
URL: https://github.com/llvm/llvm-project/commit/98d911e01f3ac62a9f78850b4209effcf2f54c91
DIFF: https://github.com/llvm/llvm-project/commit/98d911e01f3ac62a9f78850b4209effcf2f54c91.diff
LOG: Revert "Treat `std::move`, `forward`, etc. as builtins."
This reverts commit b27430f9f46b88bcd54d992debc8d72e131e1bd0 as the
parent https://reviews.llvm.org/D123345 breaks the AIX CI:
https://lab.llvm.org/buildbot/#/builders/214/builds/819
Added:
Modified:
clang/docs/CommandGuide/clang.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/Builtins.def
clang/include/clang/Basic/Builtins.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/ExprConstant.cpp
clang/lib/Analysis/BodyFarm.cpp
clang/lib/Basic/Builtins.cpp
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/CodeGen/CGCall.cpp
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaInit.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/Analysis/inner-pointer.cpp
clang/test/Analysis/use-after-move.cpp
clang/test/CodeGenCXX/builtins.cpp
clang/test/CodeGenCXX/microsoft-abi-throw.cpp
clang/test/SemaCXX/unqualified-std-call-fixits.cpp
clang/test/SemaCXX/unqualified-std-call.cpp
clang/test/SemaCXX/warn-consumed-analysis.cpp
clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
Removed:
clang/test/CodeGenCXX/builtin-std-move.cpp
clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
clang/test/SemaCXX/builtin-std-move.cpp
################################################################################
diff --git a/clang/docs/CommandGuide/clang.rst b/clang/docs/CommandGuide/clang.rst
index 658a30458043e..aec62789a43e6 100644
--- a/clang/docs/CommandGuide/clang.rst
+++ b/clang/docs/CommandGuide/clang.rst
@@ -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
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cb5cad717e347..4e63effe5769f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -250,10 +250,7 @@ C2x Feature Support
C++ Language Changes in Clang
-----------------------------
-- Improved ``-O0`` code generation for calls to ``std::move``, ``std::forward``,
- ``std::move_if_noexcept``, ``std::addressof``, and ``std::as_const``. These
- are now treated as compiler builtins and implemented directly, rather than
- instantiating the definition from the standard library.
+- ...
C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index c22957e14de7d..62e82cd36321d 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -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")
diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h
index a82e15730f992..2926e0fa2c8d6 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -138,10 +138,6 @@ class Context {
/// 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 @@ class Context {
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 @@ class Context {
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;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 26e6db82a47f4..2008f02bf9909 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6590,15 +6590,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;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 3ad44d5e2da80..6fe5d77a33fe5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8127,7 +8127,6 @@ class LValueExprEvaluator
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 (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: {
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index 95bed548c567a..92c236ed9080c 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -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 @@ class ASTMaker {
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;
diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp
index ef8bb562ac17e..6d278e9c4a229 100644
--- a/clang/lib/Basic/Builtins.cpp
+++ b/clang/lib/Basic/Builtins.cpp
@@ -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));
}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index fc2d32f3e26fe..17adc9ba75079 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2271,9 +2271,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
ReturnValueSlot ReturnValue) {
const FunctionDecl *FD = GD.getDecl()->getAsFunction();
// See if we can constant fold this builtin. If so, don't emit it at all.
- // TODO: Extend this handling to all builtin calls that we can constant-fold.
Expr::EvalResult Result;
- if (E->isPRValue() && E->EvaluateAsRValue(Result, CGM.getContext()) &&
+ if (E->EvaluateAsRValue(Result, CGM.getContext()) &&
!Result.hasSideEffects()) {
if (Result.Val.isInt())
return RValue::get(llvm::ConstantInt::get(getLLVMContext(),
@@ -4567,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:
@@ -4728,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()))
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d69455d650f43..e6a5fd1f4f985 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -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())
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 467edd3321b9d..34de3df7a80c3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -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
diff er 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:
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0c8b7fcd306b6..30164e56120ce 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9276,32 +9276,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,
@@ -10154,30 +10128,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)) {
+ 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));
- } 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));
- }
}
- } 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));
}
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3bd83b8136869..273de0867e3ed 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -3396,7 +3396,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;
@@ -20480,8 +20480,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();
@@ -20489,36 +20488,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);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 7b3a18a503816..79b670a1ec735 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4237,14 +4237,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();
}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 2a49627ecf106..c7048225c9d43 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -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:
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 1add971a81a02..33271609a0081 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -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;
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8b0147fc66c36..9d0dc8cad46b8 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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,
diff --git a/clang/test/Analysis/inner-pointer.cpp b/clang/test/Analysis/inner-pointer.cpp
index 5db17a952f90b..920a1fe8dcc9d 100644
--- a/clang/test/Analysis/inner-pointer.cpp
+++ b/clang/test/Analysis/inner-pointer.cpp
@@ -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
}
diff --git a/clang/test/Analysis/use-after-move.cpp b/clang/test/Analysis/use-after-move.cpp
index ce9b26f15360e..d1278cad4c4f2 100644
--- a/clang/test/Analysis/use-after-move.cpp
+++ b/clang/test/Analysis/use-after-move.cpp
@@ -244,7 +244,7 @@ void reinitializationTest(int i) {
A a;
if (i == 1) { // peaceful-note 2 {{'i' is not equal to 1}}
// peaceful-note at -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 at -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
}
diff --git a/clang/test/CodeGenCXX/builtin-std-move.cpp b/clang/test/CodeGenCXX/builtin-std-move.cpp
deleted file mode 100644
index 55a96dac4c57c..0000000000000
--- a/clang/test/CodeGenCXX/builtin-std-move.cpp
+++ /dev/null
@@ -1,66 +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
-
-extern "C" void take_const_int_rref(const int &&);
-// CHECK-LABEL: define {{.*}} @move_const_int(
-extern "C" void move_const_int() {
- // CHECK: store i32 5, ptr %[[N_ADDR:[^,]*]]
- const int n = 5;
- // CHECK: call {{.*}} @take_const_int_rref(ptr {{.*}} %[[N_ADDR]])
- take_const_int_rref(std::move(n));
-}
diff --git a/clang/test/CodeGenCXX/builtins.cpp b/clang/test/CodeGenCXX/builtins.cpp
index 56a29eac2490c..c1c8b51cbae6d 100644
--- a/clang/test/CodeGenCXX/builtins.cpp
+++ b/clang/test/CodeGenCXX/builtins.cpp
@@ -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
diff --git a/clang/test/CodeGenCXX/microsoft-abi-throw.cpp b/clang/test/CodeGenCXX/microsoft-abi-throw.cpp
index aa79935e42ded..92849598cf063 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-throw.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-throw.cpp
@@ -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 at 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 at 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() {
diff --git a/clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp b/clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
deleted file mode 100644
index 9185bd87bf8ab..0000000000000
--- a/clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
+++ /dev/null
@@ -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);
diff --git a/clang/test/SemaCXX/builtin-std-move.cpp b/clang/test/SemaCXX/builtin-std-move.cpp
deleted file mode 100644
index a53e57c86c14c..0000000000000
--- a/clang/test/SemaCXX/builtin-std-move.cpp
+++ /dev/null
@@ -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 at -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 at -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>'}}
diff --git a/clang/test/SemaCXX/unqualified-std-call-fixits.cpp b/clang/test/SemaCXX/unqualified-std-call-fixits.cpp
index d6f8e5e2b95ed..0b2d70c0360a3 100644
--- a/clang/test/SemaCXX/unqualified-std-call-fixits.cpp
+++ b/clang/test/SemaCXX/unqualified-std-call-fixits.cpp
@@ -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::
}
diff --git a/clang/test/SemaCXX/unqualified-std-call.cpp b/clang/test/SemaCXX/unqualified-std-call.cpp
index 0c78c26d063a9..fa66ae9f8e321 100644
--- a/clang/test/SemaCXX/unqualified-std-call.cpp
+++ b/clang/test/SemaCXX/unqualified-std-call.cpp
@@ -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 {};
diff --git a/clang/test/SemaCXX/warn-consumed-analysis.cpp b/clang/test/SemaCXX/warn-consumed-analysis.cpp
index 8e09779e64404..b4dddb6763724 100644
--- a/clang/test/SemaCXX/warn-consumed-analysis.cpp
+++ b/clang/test/SemaCXX/warn-consumed-analysis.cpp
@@ -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);
}
diff --git a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
index e6360d88a893d..a4410d330d393 100644
--- a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
+++ b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
@@ -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)) {}"
More information about the cfe-commits
mailing list