64 changes: 18 additions & 46 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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));
}
}
Expand Down
35 changes: 2 additions & 33 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -20480,45 +20480,14 @@ 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();
return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy,
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);
Expand Down
8 changes: 0 additions & 8 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
4 changes: 0 additions & 4 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
32 changes: 15 additions & 17 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
}
Expand Down
20 changes: 0 additions & 20 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,20 +621,6 @@ static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) {
return true;
}

if (const auto *BA = dyn_cast<BuiltinAttr>(A)) {
// Do not treat 'std::forward' as a builtin if it takes an rvalue reference
// type and returns an lvalue reference type. The library implementation
// will produce an error in this case; don't get in its way.
if (BA->getID() == Builtin::BIforward) {
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (FD && FD->getNumParams() >= 1 &&
FD->getParamDecl(0)->getType()->isRValueReferenceType() &&
FD->getReturnType()->isLValueReferenceType()) {
return false;
}
}
}

return true;
}

Expand Down Expand Up @@ -4785,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,
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Analysis/inner-pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions clang/test/Analysis/use-after-move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down Expand Up @@ -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
}

Expand Down
66 changes: 0 additions & 66 deletions clang/test/CodeGenCXX/builtin-std-move.cpp

This file was deleted.

18 changes: 0 additions & 18 deletions clang/test/CodeGenCXX/builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions clang/test/CodeGenCXX/microsoft-abi-throw.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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() {
Expand Down
20 changes: 0 additions & 20 deletions clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp

This file was deleted.

138 changes: 0 additions & 138 deletions clang/test/SemaCXX/builtin-std-move.cpp

This file was deleted.

12 changes: 6 additions & 6 deletions clang/test/SemaCXX/unqualified-std-call-fixits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@

namespace std {

int &&move(auto &&a) { return a; }
void move(auto &&a) {}

int &&forward(auto &a) { return a; }
void forward(auto &a) {}

} // namespace std

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::
}
6 changes: 3 additions & 3 deletions clang/test/SemaCXX/unqualified-std-call.cpp
Original file line number Diff line number Diff line change
@@ -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 {};
Expand Down
6 changes: 3 additions & 3 deletions clang/test/SemaCXX/warn-consumed-analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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&&);
}
}

Expand All @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {}"
Expand Down
2 changes: 1 addition & 1 deletion libcxx/test/std/utilities/utility/forward/forward.fail.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const A csource() {return A();}
int main(int, char**)
{
{
(void)std::forward<A&>(source()); // expected-note {{requested here}}
std::forward<A&>(source()); // expected-note {{requested here}}
// expected-error-re@*:* 1 {{static_assert failed{{.*}} "cannot forward an rvalue as an lvalue"}}
}
{
Expand Down