diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -546,7 +546,7 @@ BUILTIN(__builtin_va_end, "vA", "n") BUILTIN(__builtin_va_copy, "vAA", "n") BUILTIN(__builtin_stdarg_start, "vA.", "nt") -BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc") +BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nct") BUILTIN(__builtin_bcmp, "ivC*vC*z", "Fn") BUILTIN(__builtin_bcopy, "vv*v*z", "n") BUILTIN(__builtin_bzero, "vv*z", "nF") diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -209,6 +209,7 @@ bool Builtin::Context::canBeRedeclared(unsigned ID) const { return ID == Builtin::NotBuiltin || ID == Builtin::BI__va_start || + ID == Builtin::BI__builtin_assume_aligned || (!hasReferenceArgsOrResult(ID) && !hasCustomTypechecking(ID)) || isInStdNamespace(ID); } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -141,6 +141,15 @@ << Call->getSourceRange(); } +/// Checks that a call expression's argument count is in the desired range. This +/// is useful when doing custom type-checking on a variadic function. Returns +/// true on error. +static bool checkArgCountRange(Sema &S, CallExpr *Call, unsigned MinArgCount, + unsigned MaxArgCount) { + return checkArgCountAtLeast(S, Call, MinArgCount) || + checkArgCountAtMost(S, Call, MaxArgCount); +} + /// Checks that a call expression's argument count is the desired number. /// This is useful when doing custom type-checking. Returns true on error. static bool checkArgCount(Sema &S, CallExpr *Call, unsigned DesiredArgCount) { @@ -7643,17 +7652,15 @@ /// Handle __builtin_assume_aligned. This is declared /// as (const void*, size_t, ...) and can take one optional constant int arg. bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) { - if (checkArgCountAtMost(*this, TheCall, 3)) + if (checkArgCountRange(*this, TheCall, 2, 3)) return true; unsigned NumArgs = TheCall->getNumArgs(); Expr *FirstArg = TheCall->getArg(0); - if (auto *CE = dyn_cast(FirstArg)) - FirstArg = CE->getSubExprAsWritten(); - + { ExprResult FirstArgResult = - DefaultFunctionArrayLvalueConversion(FirstArg, /*Diagnose=*/false); + DefaultFunctionArrayLvalueConversion(FirstArg); if (FirstArgResult.isInvalid()) return true; TheCall->setArg(0, FirstArgResult.get()); diff --git a/clang/test/Sema/builtin-redecl.cpp b/clang/test/Sema/builtin-redecl.cpp --- a/clang/test/Sema/builtin-redecl.cpp +++ b/clang/test/Sema/builtin-redecl.cpp @@ -2,6 +2,8 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -x c // RUN: %clang_cc1 %s -fsyntax-only -verify -fms-compatibility +#include + // Redeclaring library builtins is OK. void exit(int); @@ -16,3 +18,9 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -x c void __va_start(__builtin_va_list*, ...); + +#ifdef __cplusplus +void *__builtin_assume_aligned(const void *, size_t, ...) noexcept; +#else +void *__builtin_assume_aligned(const void *, size_t, ...); +#endif