Re: r303317 - The constant expression evaluator should examine function arguments for non-constexpr function calls unless the EvalInfo says to stop.
Joerg Sonnenberger wrote: On Wed, May 17, 2017 at 11:56:55PM -, Nick Lewycky via cfe-commits wrote: Author: nicholas Date: Wed May 17 18:56:54 2017 New Revision: 303317 URL: http://llvm.org/viewvc/llvm-project?rev=303317&view=rev Log: The constant expression evaluator should examine function arguments for non-constexpr function calls unless the EvalInfo says to stop. Crashes with -std=c++11 on: enum SizeHint { MinimumSize, MaximumSize }; class QSizeF { public: constexpr QSizeF(); QSizeF m_fn1(QSizeF); double wd; double ht; }; constexpr QSizeF::QSizeF() : wd(), ht() {} class A { void m_fn2(); QSizeF m_fn3(SizeHint, const QSizeF& = QSizeF()); }; void A::m_fn2() { m_fn3(MinimumSize).m_fn1(m_fn3(MaximumSize)); } Did you run this with assertions disabled? This looks like another testcase for PR33140, but it should hit an assertion first. Nick ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r305233 - Revert r303316, a change to ExprConstant to evaluate function arguments.
Author: nicholas Date: Mon Jun 12 16:15:44 2017 New Revision: 305233 URL: http://llvm.org/viewvc/llvm-project?rev=305233&view=rev Log: Revert r303316, a change to ExprConstant to evaluate function arguments. The patch was itself correct but it uncovered other bugs which are going to be difficult to fix, per PR33140. Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/Sema/integer-overflow.c Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=305233&r1=305232&r2=305233&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Jun 12 16:15:44 2017 @@ -4588,7 +4588,7 @@ public: } bool handleCallExpr(const CallExpr *E, APValue &Result, - const LValue *ResultSlot) { + const LValue *ResultSlot) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); @@ -4597,23 +4597,6 @@ public: auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; -struct EvaluateIgnoredRAII { -public: - EvaluateIgnoredRAII(EvalInfo &Info, llvm::ArrayRef ToEval) - : Info(Info), ToEval(ToEval) {} - ~EvaluateIgnoredRAII() { -if (Info.noteFailure()) { - for (auto E : ToEval) -EvaluateIgnoredValue(Info, E); -} - } - void cancel() { ToEval = {}; } - void drop_front() { ToEval = ToEval.drop_front(); } -private: - EvalInfo &Info; - llvm::ArrayRef ToEval; -} EvalArguments(Info, Args); - // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { const ValueDecl *Member = nullptr; @@ -4663,12 +4646,10 @@ public: if (Args.empty()) return Error(E); -const Expr *FirstArg = Args[0]; -Args = Args.drop_front(); -EvalArguments.drop_front(); -if (!EvaluateObjectArgument(Info, FirstArg, ThisVal)) +if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) return false; This = &ThisVal; +Args = Args.slice(1); } else if (MD && MD->isLambdaStaticInvoker()) { // Map the static invoker for the lambda back to the call operator. // Conveniently, we don't have to slice out the 'this' argument (as is @@ -4720,12 +4701,8 @@ public: const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); -if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) - return false; - -EvalArguments.cancel(); - -if (!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, +if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || +!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; Modified: cfe/trunk/test/Sema/integer-overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/integer-overflow.c?rev=305233&r1=305232&r2=305233&view=diff == --- cfe/trunk/test/Sema/integer-overflow.c (original) +++ cfe/trunk/test/Sema/integer-overflow.c Mon Jun 12 16:15:44 2017 @@ -151,14 +151,6 @@ uint64_t check_integer_overflows(int i) uint64_t *b; uint64_t b2 = b[4608 * 1024 * 1024] + 1; -// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} - f0(4608 * 1024 * 1024); - f0(4608ul * 1024 * 1024); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} - f1(4608 * 1024 * 1024, 4608 * 1024 * 1024); -// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} - f2(4608 * 1024 * 1024, 4608 * 1024 * 1024); - // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} int j1 = i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r305239 - Revert r301742 which made ExprConstant checking apply to all full-exprs.
Author: nicholas Date: Mon Jun 12 16:59:18 2017 New Revision: 305239 URL: http://llvm.org/viewvc/llvm-project?rev=305239&view=rev Log: Revert r301742 which made ExprConstant checking apply to all full-exprs. This patch also exposed pre-existing bugs in clang, see PR32864 and PR33140#c3 . Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/distribute_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/simd_aligned_messages.cpp cfe/trunk/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/target_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/target_teams_distribute_parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/taskloop_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/teams_distribute_simd_aligned_messages.cpp cfe/trunk/test/Sema/integer-overflow.c Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=305239&r1=305238&r2=305239&view=diff == --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon Jun 12 16:59:18 2017 @@ -10273,6 +10273,7 @@ private: void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); void CheckBoolLikeConversion(Expr *E, SourceLocation CC); + void CheckForIntOverflow(Expr *E); void CheckUnsequencedOperations(Expr *E); /// \brief Perform semantic checks on a completed expression. This will either Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=305239&r1=305238&r2=305239&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Jun 12 16:59:18 2017 @@ -6226,10 +6226,6 @@ bool RecordExprEvaluator::VisitInitListE // the initializer list. ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType()); const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE; -if (Init->isValueDependent()) { - Success = false; - continue; -} // Temporarily override This, in case there's a CXXDefaultInitExpr in here. ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, @@ -9940,8 +9936,7 @@ static bool EvaluateAsRValue(EvalInfo &I } static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, - const ASTContext &Ctx, bool &IsConst, - bool IsCheckingForOverflow) { + const ASTContext &Ctx, bool &IsConst) { // Fast-path evaluations of integer literals, since we sometimes see files // containing vast quantities of these. if (const IntegerLiteral *L = dyn_cast(Exp)) { @@ -9962,7 +9957,7 @@ static bool FastEvaluateAsRValue(const E // performance problems. Only do so in C++11 for now. if (Exp->isRValue() && (Exp->getType()->isArrayType() || Exp->getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus11 && !IsCheckingForOverflow) { + !Ctx.getLangOpts().CPlusPlus11) { IsConst = false; return true; } @@ -9977,7 +9972,7 @@ static bool FastEvaluateAsRValue(const E /// will be applied to the result. bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { bool IsConst; - if (FastEvaluateAsRValue(this, Result, Ctx, IsConst, false)) + if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) return IsConst; EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); @@ -10102,7 +10097,7 @@ APSInt Expr::EvaluateKnownConstInt(const void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; EvalResult EvalResult; - if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst, true)) { + if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); (void)::EvaluateAsRValue(Info, this, EvalResult.Val); } Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=305239&r1=305238&r2=305239&view=diff == --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jun 12
r321665 - Suppress undefined-template warnings when the pattern is declared in a system header.
Author: nicholas Date: Tue Jan 2 11:10:12 2018 New Revision: 321665 URL: http://llvm.org/viewvc/llvm-project?rev=321665&view=rev Log: Suppress undefined-template warnings when the pattern is declared in a system header. The way to fix an undefined-template warning is to add lines to the header file that defines the template pattern. We should suppress the warnings when the template pattern is in a system header because we don't expect users to edit those. Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/SemaTemplate/undefined-template.cpp Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=321665&r1=321664&r2=321665&view=diff == --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Jan 2 11:10:12 2018 @@ -3812,7 +3812,8 @@ void Sema::InstantiateFunctionDefinition PendingInstantiations.push_back( std::make_pair(Function, PointOfInstantiation)); } else if (TSK == TSK_ImplicitInstantiation) { - if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { + if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() && + !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) { Diag(PointOfInstantiation, diag::warn_func_template_missing) << Function; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); @@ -4347,7 +4348,8 @@ void Sema::InstantiateVariableDefinition std::make_pair(Var, PointOfInstantiation)); } else if (TSK == TSK_ImplicitInstantiation) { // Warn about missing definition at the end of translation unit. - if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { + if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() && + !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) { Diag(PointOfInstantiation, diag::warn_var_template_missing) << Var; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); Modified: cfe/trunk/test/SemaTemplate/undefined-template.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/undefined-template.cpp?rev=321665&r1=321664&r2=321665&view=diff == --- cfe/trunk/test/SemaTemplate/undefined-template.cpp (original) +++ cfe/trunk/test/SemaTemplate/undefined-template.cpp Tue Jan 2 11:10:12 2018 @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -Wundefined-func-template %s +#if !defined(INCLUDE) template struct C1 { static char s_var_1; // expected-note{{forward declaration of template entity is here}} static char s_var_2; // expected-note{{forward declaration of template entity is here}} @@ -142,6 +143,16 @@ namespace test_24 { void h(X x) { g(x); } // no warning for use of 'g' despite the declaration having been instantiated from a template } +#define INCLUDE +#include "undefined-template.cpp" +void func_25(SystemHeader *x) { + x->meth(); +} + int main() { return 0; } +#else +#pragma clang system_header +template struct SystemHeader { T meth(); }; +#endif ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] r359329 - Fix typo in documentation.
Author: nicholas Date: Fri Apr 26 10:56:22 2019 New Revision: 359329 URL: http://llvm.org/viewvc/llvm-project?rev=359329&view=rev Log: Fix typo in documentation. Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-comparison.rst Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-comparison.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-comparison.rst?rev=359329&r1=359328&r2=359329&view=diff == --- clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-comparison.rst (original) +++ clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-time-comparison.rst Fri Apr 26 10:56:22 2019 @@ -6,7 +6,7 @@ abseil-time-comparison Prefer comparisons in the ``absl::Time`` domain instead of the integer domain. N.B.: In cases where an ``absl::Time`` is being converted to an integer, -alignment may occur. If the comparison depends on this alingment, doing the +alignment may occur. If the comparison depends on this alignment, doing the comparison in the ``absl::Time`` domain may yield a different result. In practice this is very rare, and still indicates a bug which should be fixed. ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D24712: Replace 'isProvablyNonNull' with existing utility llvm::IsKnownNonNull.
On 19 September 2016 at 15:58, John McCall wrote: > rjmccall added a comment. > > Actually, that should demonstrate the difference, assuming the LLVM > function looks through selects, since IRGen should generate that as a > select. > It doesn't look past the Value* you hand it. As well as isa, it returns true on Arguments marked nonnull, byval, inalloca or dereferenceable, global variables in addrspace 0 and not extern_weak, load instructions marked with !nonnull metadata, or a call/invoke with the nonnull parameter attribute on the return. It doesn't look at operands. > > https://reviews.llvm.org/D24712 > > > > ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r281979 - Replace 'isProvablyNonNull' with existing utility llvm::IsKnownNonNull which handles more cases. Noticed by inspection.
Author: nicholas Date: Tue Sep 20 10:49:58 2016 New Revision: 281979 URL: http://llvm.org/viewvc/llvm-project?rev=281979&view=rev Log: Replace 'isProvablyNonNull' with existing utility llvm::IsKnownNonNull which handles more cases. Noticed by inspection. Because of how the IR generation works, this isn't expected to cause an observable difference. Modified: cfe/trunk/lib/CodeGen/CGCall.cpp Modified: cfe/trunk/lib/CodeGen/CGCall.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=281979&r1=281978&r2=281979&view=diff == --- cfe/trunk/lib/CodeGen/CGCall.cpp (original) +++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Sep 20 10:49:58 2016 @@ -29,6 +29,7 @@ #include "clang/CodeGen/SwiftCallingConv.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/CallSite.h" @@ -2905,10 +2906,6 @@ static bool isProvablyNull(llvm::Value * return isa(addr); } -static bool isProvablyNonNull(llvm::Value *addr) { - return isa(addr); -} - /// Emit the actual writing-back of a writeback. static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { @@ -2921,7 +2918,7 @@ static void emitWriteback(CodeGenFunctio // If the argument wasn't provably non-null, we need to null check // before doing the store. - bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer()); + bool provablyNonNull = llvm::isKnownNonNull(srcAddr.getPointer()); if (!provablyNonNull) { llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); contBB = CGF.createBasicBlock("icr.done"); @@ -3061,7 +3058,7 @@ static void emitWritebackArg(CodeGenFunc // If the address is *not* known to be non-null, we need to switch. llvm::Value *finalArgument; - bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer()); + bool provablyNonNull = llvm::isKnownNonNull(srcAddr.getPointer()); if (provablyNonNull) { finalArgument = temp.getPointer(); } else { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r281996 - Fix typo in documentation.
Author: nicholas Date: Tue Sep 20 13:37:25 2016 New Revision: 281996 URL: http://llvm.org/viewvc/llvm-project?rev=281996&view=rev Log: Fix typo in documentation. Since this is a header it will break links to this section. Modified: cfe/trunk/docs/UndefinedBehaviorSanitizer.rst Modified: cfe/trunk/docs/UndefinedBehaviorSanitizer.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UndefinedBehaviorSanitizer.rst?rev=281996&r1=281995&r2=281996&view=diff == --- cfe/trunk/docs/UndefinedBehaviorSanitizer.rst (original) +++ cfe/trunk/docs/UndefinedBehaviorSanitizer.rst Tue Sep 20 13:37:25 2016 @@ -66,8 +66,8 @@ pointer. .. _ubsan-checks: -Availablle checks -= +Available checks + Available checks are: ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
patch: clean up in EmitValueForIvarAtOffset
The attached patch makes the LValue created in EmitValueForIvarAtOffset have the same Qualifiers in the LValue as the QualType in the LValue. Noticed when auditing for reasons the QualType would different from the Qualifiers in an LValue. No functionality change. Please review! Nick lvalue-qualifiers-1.patch Description: Binary data ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r283795 - Make the LValue created in EmitValueForIvarAtOffset have the same Qualifiers in the LValue as the QualType in the LValue. No functionality change intended.
Author: nicholas Date: Mon Oct 10 15:07:13 2016 New Revision: 283795 URL: http://llvm.org/viewvc/llvm-project?rev=283795&view=rev Log: Make the LValue created in EmitValueForIvarAtOffset have the same Qualifiers in the LValue as the QualType in the LValue. No functionality change intended. Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp?rev=283795&r1=283794&r2=283795&view=diff == --- cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp Mon Oct 10 15:07:13 2016 @@ -90,7 +90,7 @@ LValue CGObjCRuntime::EmitValueForIvarAt unsigned CVRQualifiers, llvm::Value *Offset) { // Compute (type*) ( (char *) BaseValue + Offset) - QualType IvarTy = Ivar->getType(); + QualType IvarTy = Ivar->getType().withCVRQualifiers(CVRQualifiers); llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy); V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr"); @@ -98,7 +98,6 @@ LValue CGObjCRuntime::EmitValueForIvarAt if (!Ivar->isBitField()) { V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); -LV.getQuals().addCVRQualifiers(CVRQualifiers); return LV; } @@ -139,9 +138,7 @@ LValue CGObjCRuntime::EmitValueForIvarAt Addr = CGF.Builder.CreateElementBitCast(Addr, llvm::Type::getIntNTy(CGF.getLLVMContext(), Info->StorageSize)); - return LValue::MakeBitfield(Addr, *Info, - IvarTy.withCVRQualifiers(CVRQualifiers), - AlignmentSource::Decl); + return LValue::MakeBitfield(Addr, *Info, IvarTy, AlignmentSource::Decl); } namespace { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D23734: Add -fprofile-dir= to clang.
nlewycky created this revision. nlewycky added subscribers: llvm-commits, cfe-commits. -fprofile-dir=path allows the user to specify where .gcda files should be emitted when the program is run. In particular, this is the first flag that causes the .gcno and .o files to have different paths, LLVM is extended to support this. -fprofile-dir= does not change the file name in the .gcno (and thus where lcov looks for the source) but it does change the name in the .gcda (and thus where the runtime library writes the .gcda file). It's different from a GCOV_PREFIX because a user can observe that the GCOV_PREFIX_STRIP will strip paths off of -fprofile-dir= but not off of a supplied GCOV_PREFIX. To implement this we split -coverage-file into -coverage-data-file and -coverage-notes-file to specify the two different names. The !llvm.gcov metadata node grows from a 2-element form {string coverage-file, node dbg.cu} to 3-elements, {string coverage-notes-file, string coverage-data-file, node dbg.cu}. In the 3-element form, the file name is already "mangled" with .gcno/.gcda suffixes, while the 2-element form left that to the middle end pass. https://reviews.llvm.org/D23734 Files: lib/Transforms/Instrumentation/GCOVProfiling.cpp test/Transforms/GCOVProfiling/three-element-mdnode.ll Index: test/Transforms/GCOVProfiling/three-element-mdnode.ll === --- test/Transforms/GCOVProfiling/three-element-mdnode.ll +++ test/Transforms/GCOVProfiling/three-element-mdnode.ll @@ -0,0 +1,27 @@ +; RUN: echo '!9 = !{!"%T/aaa.gcno", !"%T/bbb.gcda", !0}' > %t1 +; RUN: cat %s %t1 > %t2 +; RUN: opt -insert-gcov-profiling -S -o %t3 < %t2 +; RUN: grep _Z3foov %T/aaa.gcno +; RUN: grep bbb.gcda %t3 +; RUN: rm %T/aaa.gcno + +define void @_Z3foov() !dbg !5 { +entry: + ret void, !dbg !8 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!10} +!llvm.gcov = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.3 (trunk 177323)", isOptimized: false, emissionKind: FullDebug, file: !2, enums: !3, retainedTypes: !3, globals: !3, imports: !3) +!1 = !DIFile(filename: "hello.cc", directory: "/home/nlewycky") +!2 = !DIFile(filename: "hello.cc", directory: "/home/nlewycky") +!3 = !{} +!5 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !1, type: !6, variables: !3) +!6 = !DISubroutineType(types: !7) +!7 = !{null} +!8 = !DILocation(line: 1, scope: !5) + + +!10 = !{i32 1, !"Debug Info Version", i32 3} Index: lib/Transforms/Instrumentation/GCOVProfiling.cpp === --- lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -118,7 +118,8 @@ Function *insertFlush(ArrayRef>); void insertIndirectCounterIncrement(); - std::string mangleName(const DICompileUnit *CU, const char *NewStem); + enum GCovFileType { GCNO, GCDA }; + std::string mangleName(const DICompileUnit *CU, GCovFileType NewStem); GCOVOptions Options; @@ -418,24 +419,37 @@ } std::string GCOVProfiler::mangleName(const DICompileUnit *CU, - const char *NewStem) { + GCovFileType NewStem) { if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) { for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) { MDNode *N = GCov->getOperand(i); + if (N->getNumOperands() == 3) { +// These nodes have no mangling to apply, it's stored mangled in the +// bitcode. +MDString *NotesFile = dyn_cast(N->getOperand(0)); +MDString *DataFile = dyn_cast(N->getOperand(1)); +MDNode *CompileUnit = dyn_cast(N->getOperand(2)); +if (!NotesFile || !DataFile || !CompileUnit) continue; +if (CompileUnit == CU) + return NewStem == GCNO ? NotesFile->getString() + : DataFile->getString(); + } if (N->getNumOperands() != 2) continue; MDString *GCovFile = dyn_cast(N->getOperand(0)); MDNode *CompileUnit = dyn_cast(N->getOperand(1)); if (!GCovFile || !CompileUnit) continue; if (CompileUnit == CU) { -SmallString<128> Filename = GCovFile->getString(); -sys::path::replace_extension(Filename, NewStem); +SmallString<128> Filename; +Filename = GCovFile->getString(); +sys::path::replace_extension(Filename, + NewStem == GCNO ? "gcno" : "gcda"); return Filename.str(); } } } SmallString<128> Filename = CU->getFilename(); - sys::path::replace_extension(Filename, NewStem); + sys::path::replace_extension(Filename, NewStem == GCNO ? "gcno" : "gcda"); StringRef FName = sys::path::filename(Filename); SmallString<128>
Re: [PATCH] D23734: Add -fprofile-dir= to clang.
nlewycky updated this revision to Diff 68755. nlewycky added a comment. Forgot clang changes! https://reviews.llvm.org/D23734 Files: lib/Transforms/Instrumentation/GCOVProfiling.cpp test/Transforms/GCOVProfiling/three-element-mdnode.ll tools/clang/include/clang/Driver/CC1Options.td tools/clang/include/clang/Driver/Options.td tools/clang/include/clang/Frontend/CodeGenOptions.h tools/clang/lib/CodeGen/CodeGenModule.cpp tools/clang/lib/Driver/Tools.cpp tools/clang/lib/Frontend/CompilerInvocation.cpp tools/clang/test/CodeGen/code-coverage.c tools/clang/test/Driver/clang_f_opts.c tools/clang/test/Driver/coverage_no_integrated_as.c Index: tools/clang/test/Driver/coverage_no_integrated_as.c === --- tools/clang/test/Driver/coverage_no_integrated_as.c +++ tools/clang/test/Driver/coverage_no_integrated_as.c @@ -17,7 +17,7 @@ // RUN: %clang -### -c -fprofile-arcs -no-integrated-as %s -o foo/bar.o 2>&1 | FileCheck -check-prefix=CHECK-GCNO-LOCATION-REL-PATH %s -// CHECK-GCNO-DEFAULT-LOCATION: "-coverage-file" "{{.*}}{{/|}}coverage_no_integrated_as.c" -// CHECK-GCNO-DEFAULT-LOCATION-NOT: "-coverage-file" "/tmp/{{.*}}/coverage_no_integrated_as.c" -// CHECK-GCNO-LOCATION: "-coverage-file" "{{.*}}/foo/bar.o" -// CHECK-GCNO-LOCATION-REL-PATH: "-coverage-file" "{{.*}}{{/|}}foo/bar.o" +// CHECK-GCNO-DEFAULT-LOCATION: "-coverage-notes-file" "{{.*}}{{/|}}coverage_no_integrated_as.c" +// CHECK-GCNO-DEFAULT-LOCATION-NOT: "-coverage-notes-file" "/tmp/{{.*}}/coverage_no_integrated_as.c" +// CHECK-GCNO-LOCATION: "-coverage-notes-file" "{{.*}}/foo/bar.gcno" +// CHECK-GCNO-LOCATION-REL-PATH: "-coverage-notes-file" "{{.*}}{{/|}}foo/bar.gcno" Index: tools/clang/test/Driver/clang_f_opts.c === --- tools/clang/test/Driver/clang_f_opts.c +++ tools/clang/test/Driver/clang_f_opts.c @@ -66,6 +66,16 @@ // CHECK-PROFILE-ARCS: "-femit-coverage-data" // CHECK-NO-PROFILE-ARCS-NOT: "-femit-coverage-data" +// RUN: %clang -### -S -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-UNUSED %s +// RUN: %clang -### -S -ftest-coverage -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-UNUSED %s +// RUN: %clang -### -S -fprofile-arcs -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR %s +// RUN: %clang -### -S --coverage -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR %s +// RUN: %clang -### -S -fprofile-arcs -fno-profile-arcs -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-NEITHER %s +// CHECK-PROFILE-DIR: "-coverage-data-file" "abc +// CHECK-PROFILE-DIR-UNUSED: argument unused +// CHECK-PROFILE-DIR-UNUSED-NOT: "-coverage-data-file" "abc +// CHECK-PROFILE-DIR-NEITHER-NOT: argument unused + // RUN: %clang -### -S -fprofile-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-LLVM %s // RUN: %clang -### -S -fprofile-instr-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s // RUN: %clang -### -S -fprofile-generate=/some/dir %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-DIR %s @@ -212,7 +222,6 @@ // RUN: -fdefer-pop -fno-defer-pop\ // RUN: -fprefetch-loop-arrays -fno-prefetch-loop-arrays \ // RUN: -fprofile-correction -fno-profile-correction \ -// RUN: -fprofile-dir=bar \ // RUN: -fprofile-values -fno-profile-values \ // RUN: -frounding-math -fno-rounding-math\ // RUN: -fsee -fno-see\ @@ -290,7 +299,6 @@ // RUN: -fkeep-inline-functions \ // RUN: -fno-keep-inline-functions\ // RUN: -freorder-blocks \ -// RUN: -fprofile-dir=/rand/dir \ // RUN: -falign-functions \ // RUN: -falign-functions=1 \ // RUN: -ffloat-store \ @@ -357,7 +365,6 @@ // CHECK-WARNING-DAG: optimization flag '-fkeep-inline-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-fno-keep-inline-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported -// CHECK-WARNING-DAG: optimization flag '-fprofile-dir=/rand/dir' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-functions=1' is not supported // CHECK-WARNING-DAG: optimization flag '-ffloat-store' is not supported Index: tools/clang/test/CodeGen/code-cove
Re: [PATCH] D23734: Add -fprofile-dir= to clang.
nlewycky added a comment. Ping! I think the review this patch really needs is a comparison to GCC's implementation to double-check that it really does the same thing that GCC does. Is there a gcov user who could take a look at this? https://reviews.llvm.org/D23734 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D23734: Add -fprofile-dir= to clang.
nlewycky updated this revision to Diff 69778. nlewycky marked 5 inline comments as done. https://reviews.llvm.org/D23734 Files: lib/Transforms/Instrumentation/GCOVProfiling.cpp test/Transforms/GCOVProfiling/three-element-mdnode.ll tools/clang/include/clang/Driver/CC1Options.td tools/clang/include/clang/Driver/Options.td tools/clang/include/clang/Frontend/CodeGenOptions.h tools/clang/lib/CodeGen/CodeGenModule.cpp tools/clang/lib/Driver/Tools.cpp tools/clang/lib/Frontend/CompilerInvocation.cpp tools/clang/test/CodeGen/code-coverage.c tools/clang/test/Driver/clang_f_opts.c tools/clang/test/Driver/coverage_no_integrated_as.c Index: tools/clang/test/Driver/coverage_no_integrated_as.c === --- tools/clang/test/Driver/coverage_no_integrated_as.c +++ tools/clang/test/Driver/coverage_no_integrated_as.c @@ -17,7 +17,7 @@ // RUN: %clang -### -c -fprofile-arcs -no-integrated-as %s -o foo/bar.o 2>&1 | FileCheck -check-prefix=CHECK-GCNO-LOCATION-REL-PATH %s -// CHECK-GCNO-DEFAULT-LOCATION: "-coverage-file" "{{.*}}{{/|}}coverage_no_integrated_as.c" -// CHECK-GCNO-DEFAULT-LOCATION-NOT: "-coverage-file" "/tmp/{{.*}}/coverage_no_integrated_as.c" -// CHECK-GCNO-LOCATION: "-coverage-file" "{{.*}}/foo/bar.o" -// CHECK-GCNO-LOCATION-REL-PATH: "-coverage-file" "{{.*}}{{/|}}foo/bar.o" +// CHECK-GCNO-DEFAULT-LOCATION: "-coverage-notes-file" "{{.*}}{{/|}}coverage_no_integrated_as.c" +// CHECK-GCNO-DEFAULT-LOCATION-NOT: "-coverage-notes-file" "/tmp/{{.*}}/coverage_no_integrated_as.c" +// CHECK-GCNO-LOCATION: "-coverage-notes-file" "{{.*}}/foo/bar.gcno" +// CHECK-GCNO-LOCATION-REL-PATH: "-coverage-notes-file" "{{.*}}{{/|}}foo/bar.gcno" Index: tools/clang/test/Driver/clang_f_opts.c === --- tools/clang/test/Driver/clang_f_opts.c +++ tools/clang/test/Driver/clang_f_opts.c @@ -66,6 +66,16 @@ // CHECK-PROFILE-ARCS: "-femit-coverage-data" // CHECK-NO-PROFILE-ARCS-NOT: "-femit-coverage-data" +// RUN: %clang -### -S -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-UNUSED %s +// RUN: %clang -### -S -ftest-coverage -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-UNUSED %s +// RUN: %clang -### -S -fprofile-arcs -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR %s +// RUN: %clang -### -S --coverage -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR %s +// RUN: %clang -### -S -fprofile-arcs -fno-profile-arcs -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-NEITHER %s +// CHECK-PROFILE-DIR: "-coverage-data-file" "abc +// CHECK-PROFILE-DIR-UNUSED: argument unused +// CHECK-PROFILE-DIR-UNUSED-NOT: "-coverage-data-file" "abc +// CHECK-PROFILE-DIR-NEITHER-NOT: argument unused + // RUN: %clang -### -S -fprofile-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-LLVM %s // RUN: %clang -### -S -fprofile-instr-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s // RUN: %clang -### -S -fprofile-generate=/some/dir %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-DIR %s @@ -212,7 +222,6 @@ // RUN: -fdefer-pop -fno-defer-pop\ // RUN: -fprefetch-loop-arrays -fno-prefetch-loop-arrays \ // RUN: -fprofile-correction -fno-profile-correction \ -// RUN: -fprofile-dir=bar \ // RUN: -fprofile-values -fno-profile-values \ // RUN: -frounding-math -fno-rounding-math\ // RUN: -fsee -fno-see\ @@ -290,7 +299,6 @@ // RUN: -fkeep-inline-functions \ // RUN: -fno-keep-inline-functions\ // RUN: -freorder-blocks \ -// RUN: -fprofile-dir=/rand/dir \ // RUN: -falign-functions \ // RUN: -falign-functions=1 \ // RUN: -ffloat-store \ @@ -357,7 +365,6 @@ // CHECK-WARNING-DAG: optimization flag '-fkeep-inline-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-fno-keep-inline-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported -// CHECK-WARNING-DAG: optimization flag '-fprofile-dir=/rand/dir' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-functions=1' is not supported // CHECK-WARNING-DAG: optimization flag '-ffloat-store' is not supported Index: tools/clang/test/CodeGen/code-coverage.c
Re: [PATCH] D23734: Add -fprofile-dir= to clang.
nlewycky added inline comments. Comment at: lib/Transforms/Instrumentation/GCOVProfiling.cpp:447 @@ -432,3 +446,3 @@ return Filename.str(); } } compnerd wrote: > It really feels like these two cases can be collapsed. I don't see a great way to do that, so I picked the one which minimizes the cost of the common case. Having an !llvm.gcov node but no CU for the specific .o is uncommon: to get here you're building a program with some .bc's built with a frontend that emits an !llvm.gcov and some .bc's without, and then you llvm-linked them and are running the insert-gcov-profiling pass afterwards. Also, I assume that copying SmallString<128>'s around is slow, while looking up Value*'s is faster. If you have a specific idea, I'm happy to try it. I'm not thrilled with the way it's written now. Comment at: test/Transforms/GCOVProfiling/three-element-mdnode.ll:27 @@ +26,2 @@ + +!10 = !{i32 1, !"Debug Info Version", i32 3} The way this test was written, !10 would be parsed before !9. Swizzled it around to make !9 the !llvm.module.flags and !10 the !llvm.gcov node. https://reviews.llvm.org/D23734 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D23734: Add -fprofile-dir= to clang.
nlewycky updated this revision to Diff 69905. https://reviews.llvm.org/D23734 Files: lib/Transforms/Instrumentation/GCOVProfiling.cpp test/Transforms/GCOVProfiling/three-element-mdnode.ll tools/clang/include/clang/Driver/CC1Options.td tools/clang/include/clang/Driver/Options.td tools/clang/include/clang/Frontend/CodeGenOptions.h tools/clang/lib/CodeGen/CodeGenModule.cpp tools/clang/lib/Driver/Tools.cpp tools/clang/lib/Frontend/CompilerInvocation.cpp tools/clang/test/CodeGen/code-coverage.c tools/clang/test/Driver/clang_f_opts.c tools/clang/test/Driver/coverage_no_integrated_as.c Index: tools/clang/test/Driver/coverage_no_integrated_as.c === --- tools/clang/test/Driver/coverage_no_integrated_as.c +++ tools/clang/test/Driver/coverage_no_integrated_as.c @@ -17,7 +17,7 @@ // RUN: %clang -### -c -fprofile-arcs -no-integrated-as %s -o foo/bar.o 2>&1 | FileCheck -check-prefix=CHECK-GCNO-LOCATION-REL-PATH %s -// CHECK-GCNO-DEFAULT-LOCATION: "-coverage-file" "{{.*}}{{/|}}coverage_no_integrated_as.c" -// CHECK-GCNO-DEFAULT-LOCATION-NOT: "-coverage-file" "/tmp/{{.*}}/coverage_no_integrated_as.c" -// CHECK-GCNO-LOCATION: "-coverage-file" "{{.*}}/foo/bar.o" -// CHECK-GCNO-LOCATION-REL-PATH: "-coverage-file" "{{.*}}{{/|}}foo/bar.o" +// CHECK-GCNO-DEFAULT-LOCATION: "-coverage-notes-file" "{{.*}}{{/|}}coverage_no_integrated_as.c" +// CHECK-GCNO-DEFAULT-LOCATION-NOT: "-coverage-notes-file" "/tmp/{{.*}}/coverage_no_integrated_as.c" +// CHECK-GCNO-LOCATION: "-coverage-notes-file" "{{.*}}/foo/bar.gcno" +// CHECK-GCNO-LOCATION-REL-PATH: "-coverage-notes-file" "{{.*}}{{/|}}foo/bar.gcno" Index: tools/clang/test/Driver/clang_f_opts.c === --- tools/clang/test/Driver/clang_f_opts.c +++ tools/clang/test/Driver/clang_f_opts.c @@ -66,6 +66,16 @@ // CHECK-PROFILE-ARCS: "-femit-coverage-data" // CHECK-NO-PROFILE-ARCS-NOT: "-femit-coverage-data" +// RUN: %clang -### -S -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-UNUSED %s +// RUN: %clang -### -S -ftest-coverage -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-UNUSED %s +// RUN: %clang -### -S -fprofile-arcs -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR %s +// RUN: %clang -### -S --coverage -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR %s +// RUN: %clang -### -S -fprofile-arcs -fno-profile-arcs -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-NEITHER %s +// CHECK-PROFILE-DIR: "-coverage-data-file" "abc +// CHECK-PROFILE-DIR-UNUSED: argument unused +// CHECK-PROFILE-DIR-UNUSED-NOT: "-coverage-data-file" "abc +// CHECK-PROFILE-DIR-NEITHER-NOT: argument unused + // RUN: %clang -### -S -fprofile-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-LLVM %s // RUN: %clang -### -S -fprofile-instr-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s // RUN: %clang -### -S -fprofile-generate=/some/dir %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-DIR %s @@ -212,7 +222,6 @@ // RUN: -fdefer-pop -fno-defer-pop\ // RUN: -fprefetch-loop-arrays -fno-prefetch-loop-arrays \ // RUN: -fprofile-correction -fno-profile-correction \ -// RUN: -fprofile-dir=bar \ // RUN: -fprofile-values -fno-profile-values \ // RUN: -frounding-math -fno-rounding-math\ // RUN: -fsee -fno-see\ @@ -290,7 +299,6 @@ // RUN: -fkeep-inline-functions \ // RUN: -fno-keep-inline-functions\ // RUN: -freorder-blocks \ -// RUN: -fprofile-dir=/rand/dir \ // RUN: -falign-functions \ // RUN: -falign-functions=1 \ // RUN: -ffloat-store \ @@ -357,7 +365,6 @@ // CHECK-WARNING-DAG: optimization flag '-fkeep-inline-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-fno-keep-inline-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported -// CHECK-WARNING-DAG: optimization flag '-fprofile-dir=/rand/dir' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-falign-functions=1' is not supported // CHECK-WARNING-DAG: optimization flag '-ffloat-store' is not supported Index: tools/clang/test/CodeGen/code-coverage.c ===
r280306 - Add -fprofile-dir= to clang.
Author: nicholas Date: Wed Aug 31 18:04:32 2016 New Revision: 280306 URL: http://llvm.org/viewvc/llvm-project?rev=280306&view=rev Log: Add -fprofile-dir= to clang. -fprofile-dir=path allows the user to specify where .gcda files should be emitted when the program is run. In particular, this is the first flag that causes the .gcno and .o files to have different paths, LLVM is extended to support this. -fprofile-dir= does not change the file name in the .gcno (and thus where lcov looks for the source) but it does change the name in the .gcda (and thus where the runtime library writes the .gcda file). It's different from a GCOV_PREFIX because a user can observe that the GCOV_PREFIX_STRIP will strip paths off of -fprofile-dir= but not off of a supplied GCOV_PREFIX. To implement this we split -coverage-file into -coverage-data-file and -coverage-notes-file to specify the two different names. The !llvm.gcov metadata node grows from a 2-element form {string coverage-file, node dbg.cu} to 3-elements, {string coverage-notes-file, string coverage-data-file, node dbg.cu}. In the 3-element form, the file name is already "mangled" with .gcno/.gcda suffixes, while the 2-element form left that to the middle end pass. Modified: cfe/trunk/include/clang/Driver/CC1Options.td cfe/trunk/include/clang/Driver/Options.td cfe/trunk/include/clang/Frontend/CodeGenOptions.h cfe/trunk/lib/CodeGen/CodeGenModule.cpp cfe/trunk/lib/Driver/Tools.cpp cfe/trunk/lib/Frontend/CompilerInvocation.cpp cfe/trunk/test/CodeGen/code-coverage.c cfe/trunk/test/Driver/clang_f_opts.c cfe/trunk/test/Driver/coverage_no_integrated_as.c Modified: cfe/trunk/include/clang/Driver/CC1Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=280306&r1=280305&r2=280306&view=diff == --- cfe/trunk/include/clang/Driver/CC1Options.td (original) +++ cfe/trunk/include/clang/Driver/CC1Options.td Wed Aug 31 18:04:32 2016 @@ -192,9 +192,14 @@ def femit_coverage_notes : Flag<["-"], " HelpText<"Emit a gcov coverage notes file when compiling.">; def femit_coverage_data: Flag<["-"], "femit-coverage-data">, HelpText<"Instrument the program to emit gcov coverage data when run.">; -def coverage_file : Separate<["-"], "coverage-file">, - HelpText<"Emit coverage data to this filename. The extension will be replaced.">; -def coverage_file_EQ : Joined<["-"], "coverage-file=">, Alias; +def coverage_data_file : Separate<["-"], "coverage-data-file">, + HelpText<"Emit coverage data to this filename.">; +def coverage_data_file_EQ : Joined<["-"], "coverage-data-file=">, + Alias; +def coverage_notes_file : Separate<["-"], "coverage-notes-file">, + HelpText<"Emit coverage notes to this filename.">; +def coverage_notes_file_EQ : Joined<["-"], "coverage-notes-file=">, + Alias; def coverage_cfg_checksum : Flag<["-"], "coverage-cfg-checksum">, HelpText<"Emit CFG checksum for functions in .gcno files.">; def coverage_no_function_names_in_data : Flag<["-"], "coverage-no-function-names-in-data">, Modified: cfe/trunk/include/clang/Driver/Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=280306&r1=280305&r2=280306&view=diff == --- cfe/trunk/include/clang/Driver/Options.td (original) +++ cfe/trunk/include/clang/Driver/Options.td Wed Aug 31 18:04:32 2016 @@ -2117,7 +2117,7 @@ multiclass BooleanFFlag { defm : BooleanFFlag<"keep-inline-functions">, Group; -def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group; +def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group; def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group; Modified: cfe/trunk/include/clang/Frontend/CodeGenOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CodeGenOptions.h?rev=280306&r1=280305&r2=280306&view=diff == --- cfe/trunk/include/clang/Frontend/CodeGenOptions.h (original) +++ cfe/trunk/include/clang/Frontend/CodeGenOptions.h Wed Aug 31 18:04:32 2016 @@ -99,9 +99,13 @@ public: /// The code model to use (-mcmodel). std::string CodeModel; - /// The filename with path we use for coverage files. The extension will be - /// replaced. - std::string CoverageFile; + /// The filename with path we use for coverage data files. The runtime + /// allows further manipulation with the GCOV_PREFIX and GCOV_PREFIX_STRIP + /// environment variables. + std::string CoverageDataFile; + + /// The filename with path we use for coverage notes files. + std::string CoverageNotesFile; /// The version string to put into coverage files. char CoverageVersion[4]; Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=280306&r1=280305&r2=28
Re: [PATCH] D16171: Warning on redeclaring with a conflicting asm label
On 11 September 2016 at 21:14, Sam Shepperd via cfe-commits < cfe-commits@lists.llvm.org> wrote: > phabricss added a subscriber: phabricss. > phabricss added a comment. > > It is still impossible to compile glibc with clang due to this bug. Could > this patch be reviewed please. > Firstly, I thought glibc had applied a patch to fix this bug? As in, the error is correct and glibc fixed their bug? As for the patch, its goal is to only demote an error to warning when the function with conflicting asm labels is never used. That's pretty clearly a workaround (if you ever call acoshl, then you'll get an error), but moreover the check is implemented incorrectly. "New->isUsed()" will be performed at the moment the new declaration is being parsed; of course it hasn't been used yet. isUsed() will turn true only after it's used, after we actually parse the rest of the code and build AST for the uses of the new declaration. As I suggested in my last review comment, you would need to defer the check until ActOnEndOfTranslationUnit in order to correctly answer New->isUsed(). Or just not try to implement this workaround, and instead change how codegen works so that we emit calls to functions with the same asm label that gcc would choose. https://reviews.llvm.org/D16171 > > > > ___ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r295006 - When the new expr's array size is an ICE, emit it as a constant expression.
Author: nicholas Date: Mon Feb 13 17:49:55 2017 New Revision: 295006 URL: http://llvm.org/viewvc/llvm-project?rev=295006&view=rev Log: When the new expr's array size is an ICE, emit it as a constant expression. This bypasses integer sanitization checks which are redundant on the expression since it's been checked by Sema. Fixes a clang codegen assertion on "void test() { new int[0+1]{0}; }" when building with -fsanitize=signed-integer-overflow. Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp cfe/trunk/test/CodeGenCXX/new-array-init.cpp Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=295006&r1=295005&r2=295006&view=diff == --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Mon Feb 13 17:49:55 2017 @@ -659,7 +659,10 @@ static llvm::Value *EmitCXXNewAllocSize( // Emit the array size expression. // We multiply the size of all dimensions for NumElements. // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6. - numElements = CGF.EmitScalarExpr(e->getArraySize()); + numElements = CGF.CGM.EmitConstantExpr(e->getArraySize(), + CGF.getContext().getSizeType(), &CGF); + if (!numElements) +numElements = CGF.EmitScalarExpr(e->getArraySize()); assert(isa(numElements->getType())); // The number of elements can be have an arbitrary integer type; Modified: cfe/trunk/test/CodeGenCXX/new-array-init.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new-array-init.cpp?rev=295006&r1=295005&r2=295006&view=diff == --- cfe/trunk/test/CodeGenCXX/new-array-init.cpp (original) +++ cfe/trunk/test/CodeGenCXX/new-array-init.cpp Mon Feb 13 17:49:55 2017 @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -fsanitize=signed-integer-overflow -o - | FileCheck --check-prefix=SIO %s // CHECK: @[[ABC4:.*]] = {{.*}} constant [4 x i8] c"abc\00" // CHECK: @[[ABC15:.*]] = {{.*}} constant [15 x i8] c"abc\00\00\00\00 @@ -116,3 +117,9 @@ void aggr_sufficient(int n) { struct Aggr { int a, b; }; new Aggr[n] { 1, 2, 3 }; } + +// SIO-LABEL: define void @_Z14constexpr_testv +void constexpr_test() { + // SIO: call i8* @_Zna{{.}}(i32 4) + new int[0+1]{0}; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r301138 - Fix typo in comment.
Author: nicholas Date: Sun Apr 23 15:46:58 2017 New Revision: 301138 URL: http://llvm.org/viewvc/llvm-project?rev=301138&view=rev Log: Fix typo in comment. Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=301138&r1=301137&r2=301138&view=diff == --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Sun Apr 23 15:46:58 2017 @@ -1406,7 +1406,7 @@ const internal::VariadicDynCastAllOfMatc /// /// Example: Given /// \code -/// struct T {void func()}; +/// struct T {void func();}; /// T f(); /// void g(T); /// \endcode ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r301520 - In the expression evaluator, descend into both the true and false expressions of a ConditionalOperator when the condition can't be evaluated and we're in an evaluation mode that says we shou
Author: nicholas Date: Thu Apr 27 02:11:09 2017 New Revision: 301520 URL: http://llvm.org/viewvc/llvm-project?rev=301520&view=rev Log: In the expression evaluator, descend into both the true and false expressions of a ConditionalOperator when the condition can't be evaluated and we're in an evaluation mode that says we should continue evaluating. Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/Sema/integer-overflow.c Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=301520&r1=301519&r2=301520&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Apr 27 02:11:09 2017 @@ -4418,8 +4418,14 @@ private: bool HandleConditionalOperator(const ConditionalOperator *E) { bool BoolResult; if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) { - if (Info.checkingPotentialConstantExpression() && Info.noteFailure()) + if (Info.checkingPotentialConstantExpression() && Info.noteFailure()) { CheckPotentialConstantConditional(E); +return false; + } + if (Info.noteFailure()) { +StmtVisitorTy::Visit(E->getTrueExpr()); +StmtVisitorTy::Visit(E->getFalseExpr()); + } return false; } Modified: cfe/trunk/test/Sema/integer-overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/integer-overflow.c?rev=301520&r1=301519&r2=301520&view=diff == --- cfe/trunk/test/Sema/integer-overflow.c (original) +++ cfe/trunk/test/Sema/integer-overflow.c Thu Apr 27 02:11:09 2017 @@ -148,6 +148,9 @@ uint64_t check_integer_overflows(int i) a[4608 * 1024 * 1024] = 1i; // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} + (void)((i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)) + 1); + +// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r301522 - In the expression evaluator, visit the index of an ArraySubscriptExpr even if we can't evaluate the base, if the evaluation mode tells us to continue evaluation.
Author: nicholas Date: Thu Apr 27 02:27:36 2017 New Revision: 301522 URL: http://llvm.org/viewvc/llvm-project?rev=301522&view=rev Log: In the expression evaluator, visit the index of an ArraySubscriptExpr even if we can't evaluate the base, if the evaluation mode tells us to continue evaluation. Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/Sema/integer-overflow.c Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=301522&r1=301521&r2=301522&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Apr 27 02:27:36 2017 @@ -5246,14 +5246,19 @@ bool LValueExprEvaluator::VisitArraySubs if (E->getBase()->getType()->isVectorType()) return Error(E); - if (!evaluatePointer(E->getBase(), Result)) -return false; + bool Success = true; + if (!evaluatePointer(E->getBase(), Result)) { +if (!Info.noteFailure()) + return false; +Success = false; + } APSInt Index; if (!EvaluateInteger(E->getIdx(), Index, Info)) return false; - return HandleLValueArrayAdjustment(Info, E, Result, E->getType(), Index); + return Success && + HandleLValueArrayAdjustment(Info, E, Result, E->getType(), Index); } bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { Modified: cfe/trunk/test/Sema/integer-overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/integer-overflow.c?rev=301522&r1=301521&r2=301522&view=diff == --- cfe/trunk/test/Sema/integer-overflow.c (original) +++ cfe/trunk/test/Sema/integer-overflow.c Thu Apr 27 02:27:36 2017 @@ -147,6 +147,10 @@ uint64_t check_integer_overflows(int i) uint64_t a[10]; a[4608 * 1024 * 1024] = 1i; +// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}} + uint64_t *b; + uint64_t b2 = b[4608 * 1024 * 1024] + 1; + // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} (void)((i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)) + 1); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r301721 - ObjCBoxedExpr can't be evaluated by the constant expression evaluator.
Author: nicholas Date: Fri Apr 28 19:07:27 2017 New Revision: 301721 URL: http://llvm.org/viewvc/llvm-project?rev=301721&view=rev Log: ObjCBoxedExpr can't be evaluated by the constant expression evaluator. A boxed expression evaluates its subexpr and then calls an objc method to transform it into another value with pointer type. The objc method can never be constexpr and therefore this expression can never be evaluated. Fixes a miscompile boxing expressions with side-effects. Also make ObjCBoxedExpr handling a normal part of the expression evaluator instead of being the only case besides full-expression where we check for integer overflow. Added: cfe/trunk/test/CodeGenObjCXX/boxing.mm Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/lib/Sema/SemaExprObjC.cpp Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=301721&r1=301720&r2=301721&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Apr 28 19:07:27 2017 @@ -5481,8 +5481,11 @@ public: bool VisitUnaryAddrOf(const UnaryOperator *E); bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return Success(E); } - bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) - { return Success(E); } + bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { +if (Info.noteFailure()) + EvaluateIgnoredValue(Info, E->getSubExpr()); +return Error(E); + } bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } bool VisitCallExpr(const CallExpr *E); Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=301721&r1=301720&r2=301721&view=diff == --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Apr 28 19:07:27 2017 @@ -9882,6 +9882,9 @@ void Sema::CheckForIntOverflow (Expr *E) if (auto InitList = dyn_cast(E)) Exprs.append(InitList->inits().begin(), InitList->inits().end()); + +if (isa(E)) + E->IgnoreParenCasts()->EvaluateForOverflow(Context); } while (!Exprs.empty()); } Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=301721&r1=301720&r2=301721&view=diff == --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Fri Apr 28 19:07:27 2017 @@ -595,7 +595,6 @@ ExprResult Sema::BuildObjCBoxedExpr(Sour break; } } -CheckForIntOverflow(ValueExpr); // FIXME: Do I need to do anything special with BoolTy expressions? // Look for the appropriate method within NSNumber. Added: cfe/trunk/test/CodeGenObjCXX/boxing.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/boxing.mm?rev=301721&view=auto == --- cfe/trunk/test/CodeGenObjCXX/boxing.mm (added) +++ cfe/trunk/test/CodeGenObjCXX/boxing.mm Fri Apr 28 19:07:27 2017 @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +@interface NSNumber ++ (id)numberWithInt:(int)n; +@end + +int n = 1; +int m = (@(n++), 0); + +// CHECK: define {{.*}} @__cxx_global_var_init() +// CHECK: load i32, i32* @n +// CHECK: store i32 %{{.*}}, i32* @n ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r301742 - Remove Sema::CheckForIntOverflow, and instead check all full-expressions.
Author: nicholas Date: Sat Apr 29 04:33:46 2017 New Revision: 301742 URL: http://llvm.org/viewvc/llvm-project?rev=301742&view=rev Log: Remove Sema::CheckForIntOverflow, and instead check all full-expressions. CheckForIntOverflow used to implement a whitelist of top-level expressions to send to the constant expression evaluator, which handled many more expressions than the CheckForIntOverflow whitelist did. Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/distribute_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/simd_aligned_messages.cpp cfe/trunk/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/target_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/target_teams_distribute_parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/target_teams_distribute_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/taskloop_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp cfe/trunk/test/OpenMP/teams_distribute_simd_aligned_messages.cpp cfe/trunk/test/Sema/integer-overflow.c Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=301742&r1=301741&r2=301742&view=diff == --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Sat Apr 29 04:33:46 2017 @@ -10160,7 +10160,6 @@ private: void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); void CheckBoolLikeConversion(Expr *E, SourceLocation CC); - void CheckForIntOverflow(Expr *E); void CheckUnsequencedOperations(Expr *E); /// \brief Perform semantic checks on a completed expression. This will either Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=301742&r1=301741&r2=301742&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Sat Apr 29 04:33:46 2017 @@ -6217,6 +6217,10 @@ bool RecordExprEvaluator::VisitInitListE // the initializer list. ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType()); const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE; +if (Init->isValueDependent()) { + Success = false; + continue; +} // Temporarily override This, in case there's a CXXDefaultInitExpr in here. ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, @@ -9927,7 +9931,8 @@ static bool EvaluateAsRValue(EvalInfo &I } static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, - const ASTContext &Ctx, bool &IsConst) { + const ASTContext &Ctx, bool &IsConst, + bool IsCheckingForOverflow) { // Fast-path evaluations of integer literals, since we sometimes see files // containing vast quantities of these. if (const IntegerLiteral *L = dyn_cast(Exp)) { @@ -9948,7 +9953,7 @@ static bool FastEvaluateAsRValue(const E // performance problems. Only do so in C++11 for now. if (Exp->isRValue() && (Exp->getType()->isArrayType() || Exp->getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus11) { + !Ctx.getLangOpts().CPlusPlus11 && !IsCheckingForOverflow) { IsConst = false; return true; } @@ -9963,7 +9968,7 @@ static bool FastEvaluateAsRValue(const E /// will be applied to the result. bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { bool IsConst; - if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) + if (FastEvaluateAsRValue(this, Result, Ctx, IsConst, false)) return IsConst; EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); @@ -10088,7 +10093,7 @@ APSInt Expr::EvaluateKnownConstInt(const void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; EvalResult EvalResult; - if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { + if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst, true)) { EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); (void)::EvaluateAsRValue(Info, this, EvalResult.Val); } Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=301742&r1=301741&r2=301742&view=diff ===
r301785 - Handle expressions with non-literal types like ignored expressions if we are supposed to continue evaluating them.
Author: nicholas Date: Sun Apr 30 21:03:23 2017 New Revision: 301785 URL: http://llvm.org/viewvc/llvm-project?rev=301785&view=rev Log: Handle expressions with non-literal types like ignored expressions if we are supposed to continue evaluating them. Also fix a crash casting a derived nullptr to a virtual base. Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/Sema/integer-overflow.c cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=301785&r1=301784&r2=301785&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Apr 30 21:03:23 2017 @@ -2169,6 +2169,9 @@ static bool HandleLValueBase(EvalInfo &I if (!Base->isVirtual()) return HandleLValueDirectBase(Info, E, Obj, DerivedDecl, BaseDecl); + if (!Obj.checkNullPointer(Info, E, CSK_Base)) +return false; + SubobjectDesignator &D = Obj.Designator; if (D.Invalid) return false; @@ -9913,8 +9916,11 @@ static bool EvaluateAsRValue(EvalInfo &I if (E->getType().isNull()) return false; - if (!CheckLiteralType(Info, E)) + if (!CheckLiteralType(Info, E)) { +if (Info.noteFailure()) + EvaluateIgnoredValue(Info, E); return false; + } if (!::Evaluate(Result, Info, E)) return false; Modified: cfe/trunk/test/Sema/integer-overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/integer-overflow.c?rev=301785&r1=301784&r2=301785&view=diff == --- cfe/trunk/test/Sema/integer-overflow.c (original) +++ cfe/trunk/test/Sema/integer-overflow.c Sun Apr 30 21:03:23 2017 @@ -149,16 +149,16 @@ uint64_t check_integer_overflows(int i) // expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}} uint64_t *b; - uint64_t b2 = b[4608 * 1024 * 1024] + 1; + (void)b[4608 * 1024 * 1024] + 1; // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} - int j1 = i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024); + (void)(i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)); // expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} - int j2 = -(4608 * 1024 * 1024); + (void)(-(4608 * 1024 * 1024)); // expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} - uint64_t j3 = b[4608 * 1024 * 1024]; + (void)b[4608 * 1024 * 1024]; // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))); Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=301785&r1=301784&r2=301785&view=diff == --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original) +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Sun Apr 30 21:03:23 2017 @@ -60,6 +60,10 @@ namespace DerivedToVBaseCast { static_assert((U*)&d == w, ""); static_assert((U*)&d == x, ""); + // expected-error@+2 {{constexpr variable 'a' must be initialized by a constant expression}} + // expected-warning@+1 {{binding dereferenced null pointer to reference has undefined behavior}} + constexpr A &a = *((B*)0); // expected-note {{cannot access base class of null pointer}} + struct X {}; struct Y1 : virtual X {}; struct Y2 : X {}; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r301787 - Fix test that was incorrected merged between patches.
Author: nicholas Date: Sun Apr 30 21:20:06 2017 New Revision: 301787 URL: http://llvm.org/viewvc/llvm-project?rev=301787&view=rev Log: Fix test that was incorrected merged between patches. Modified: cfe/trunk/test/Sema/integer-overflow.c Modified: cfe/trunk/test/Sema/integer-overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/integer-overflow.c?rev=301787&r1=301786&r2=301787&view=diff == --- cfe/trunk/test/Sema/integer-overflow.c (original) +++ cfe/trunk/test/Sema/integer-overflow.c Sun Apr 30 21:20:06 2017 @@ -149,7 +149,7 @@ uint64_t check_integer_overflows(int i) // expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}} uint64_t *b; - (void)b[4608 * 1024 * 1024] + 1; + (void)b[4608 * 1024 * 1024]; // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} (void)(i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r301891 - Revert r301785 (and r301787) because they caused PR32864.
Author: nicholas Date: Mon May 1 20:06:16 2017 New Revision: 301891 URL: http://llvm.org/viewvc/llvm-project?rev=301891&view=rev Log: Revert r301785 (and r301787) because they caused PR32864. The fix is that ExprEvaluatorBase::VisitInitListExpr should handle transparent exprs instead of exprs with one element. Fixing that uncovers one testcase failure because the AST for "constexpr _Complex float test2 = {1};" is wrong (the _Complex prvalue should not be const-qualified), and a number of test failures in test/OpenMP where the captured stmt contains an InitListExpr that is in syntactic form. Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/Sema/integer-overflow.c cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=301891&r1=301890&r2=301891&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Mon May 1 20:06:16 2017 @@ -2186,9 +2186,6 @@ static bool HandleLValueBase(EvalInfo &I if (!Base->isVirtual()) return HandleLValueDirectBase(Info, E, Obj, DerivedDecl, BaseDecl); - if (!Obj.checkNullPointer(Info, E, CSK_Base)) -return false; - SubobjectDesignator &D = Obj.Designator; if (D.Invalid) return false; @@ -9946,11 +9943,8 @@ static bool EvaluateAsRValue(EvalInfo &I if (E->getType().isNull()) return false; - if (!CheckLiteralType(Info, E)) { -if (Info.noteFailure()) - EvaluateIgnoredValue(Info, E); + if (!CheckLiteralType(Info, E)) return false; - } if (!::Evaluate(Result, Info, E)) return false; Modified: cfe/trunk/test/Sema/integer-overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/integer-overflow.c?rev=301891&r1=301890&r2=301891&view=diff == --- cfe/trunk/test/Sema/integer-overflow.c (original) +++ cfe/trunk/test/Sema/integer-overflow.c Mon May 1 20:06:16 2017 @@ -149,16 +149,16 @@ uint64_t check_integer_overflows(int i) // expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}} uint64_t *b; - (void)b[4608 * 1024 * 1024]; + uint64_t b2 = b[4608 * 1024 * 1024] + 1; // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} - (void)(i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)); + int j1 = i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024); // expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} - (void)(-(4608 * 1024 * 1024)); + int j2 = -(4608 * 1024 * 1024); // expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} - (void)b[4608 * 1024 * 1024]; + uint64_t j3 = b[4608 * 1024 * 1024]; // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))); Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=301891&r1=301890&r2=301891&view=diff == --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original) +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Mon May 1 20:06:16 2017 @@ -60,10 +60,6 @@ namespace DerivedToVBaseCast { static_assert((U*)&d == w, ""); static_assert((U*)&d == x, ""); - // expected-error@+2 {{constexpr variable 'a' must be initialized by a constant expression}} - // expected-warning@+1 {{binding dereferenced null pointer to reference has undefined behavior}} - constexpr A &a = *((B*)0); // expected-note {{cannot access base class of null pointer}} - struct X {}; struct Y1 : virtual X {}; struct Y2 : X {}; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r303317 - The constant expression evaluator should examine function arguments for non-constexpr function calls unless the EvalInfo says to stop.
Author: nicholas Date: Wed May 17 18:56:54 2017 New Revision: 303317 URL: http://llvm.org/viewvc/llvm-project?rev=303317&view=rev Log: The constant expression evaluator should examine function arguments for non-constexpr function calls unless the EvalInfo says to stop. Modified: cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/test/Sema/integer-overflow.c Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=303317&r1=303316&r2=303317&view=diff == --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed May 17 18:56:54 2017 @@ -4579,7 +4579,7 @@ public: } bool handleCallExpr(const CallExpr *E, APValue &Result, - const LValue *ResultSlot) { + const LValue *ResultSlot) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); @@ -4588,6 +4588,23 @@ public: auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; +struct EvaluateIgnoredRAII { +public: + EvaluateIgnoredRAII(EvalInfo &Info, llvm::ArrayRef ToEval) + : Info(Info), ToEval(ToEval) {} + ~EvaluateIgnoredRAII() { +if (Info.noteFailure()) { + for (auto E : ToEval) +EvaluateIgnoredValue(Info, E); +} + } + void cancel() { ToEval = {}; } + void drop_front() { ToEval = ToEval.drop_front(); } +private: + EvalInfo &Info; + llvm::ArrayRef ToEval; +} EvalArguments(Info, Args); + // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { const ValueDecl *Member = nullptr; @@ -4637,10 +4654,12 @@ public: if (Args.empty()) return Error(E); -if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) +const Expr *FirstArg = Args[0]; +Args = Args.drop_front(); +EvalArguments.drop_front(); +if (!EvaluateObjectArgument(Info, FirstArg, ThisVal)) return false; This = &ThisVal; -Args = Args.slice(1); } else if (MD && MD->isLambdaStaticInvoker()) { // Map the static invoker for the lambda back to the call operator. // Conveniently, we don't have to slice out the 'this' argument (as is @@ -4692,8 +4711,12 @@ public: const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); -if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || -!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, +if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) + return false; + +EvalArguments.cancel(); + +if (!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; Modified: cfe/trunk/test/Sema/integer-overflow.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/integer-overflow.c?rev=303317&r1=303316&r2=303317&view=diff == --- cfe/trunk/test/Sema/integer-overflow.c (original) +++ cfe/trunk/test/Sema/integer-overflow.c Wed May 17 18:56:54 2017 @@ -151,6 +151,14 @@ uint64_t check_integer_overflows(int i) uint64_t *b; uint64_t b2 = b[4608 * 1024 * 1024] + 1; +// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} + f0(4608 * 1024 * 1024); + f0(4608ul * 1024 * 1024); +// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} + f1(4608 * 1024 * 1024, 4608 * 1024 * 1024); +// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} + f2(4608 * 1024 * 1024, 4608 * 1024 * 1024); + // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} int j1 = i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12719: ScalarEvolution assume hanging bugfix
nlewycky added inline comments. Comment at: lib/Analysis/ScalarEvolution.cpp:6980 @@ -6991,1 +6979,3 @@ + // Check conditions due to any @llvm.assume intrinsics. + for (auto &AssumeVH : AC.assumptions()) { What is it about this check which is a problem? Or put another way, why is this not okay but the call to isImpliedCond on line 6956 is fine? The problem is recursion through isImpliedCond->getSCEV->..., right? http://reviews.llvm.org/D12719 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12719: ScalarEvolution assume hanging bugfix
nlewycky added inline comments. Comment at: lib/Analysis/ScalarEvolution.cpp:6980 @@ -6991,1 +6979,3 @@ + // Check conditions due to any @llvm.assume intrinsics. + for (auto &AssumeVH : AC.assumptions()) { Prazek wrote: > nlewycky wrote: > > What is it about this check which is a problem? Or put another way, why is > > this not okay but the call to isImpliedCond on line 6956 is fine? The > > problem is recursion through isImpliedCond->getSCEV->..., right? > The problem is that the check wasn't covering assume loop which caused big > hang. > > Stacktrace looked more like this > (isImpliedCond -> getZeroExtendExpr -> isLoopBackedgeGuardedByCond) x much Does the code from 6953 to 6959 need to move below this check too? Is there another bug here? http://reviews.llvm.org/D12719 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D12719: ScalarEvolution assume hanging bugfix
On 8 September 2015 at 20:27, Sanjoy Das wrote: > sanjoy added a comment. > > I don't think this is an infinite loop (Piotr, can you please verify > this?), it is probably an O(n!) recursion where n == number of the > assumptions. > > ScalarEvolution::isImpliedCond already guards for infinite loops via > MarkPendingLoopPredicate. However, if you have > > assume_0() > assume_1() > assume_2() > assume_3() > > then the recursive call to isImpliedCond(assume_2, X) may end up > calling isImpliedCond(assume_1, Y) and that may end up calling > isImpliedCond(assume_0, Y) and that may end up calling > isImpliedCond(assume_3, Y). This way, even though we're protected > against full on infinite recursion, we'll still explore all 4! = 24 > possibilities. > I agree it's probably O(n!) instead of infinite, but that's slow enough. I think the check with LoopContinuePredicate is fine since it only > calls isImpliedCond if there is exactly one latch in the loop. This > means that the above n! possibility is really only a 1! = 1 > possibility for LoopContinuePredicate. > > But this from memory, so please double check. > Both tests are protected by there being exactly one latch in the loop (we exit early if there's not one latch). I'm not sure what makes the LoopContinuePredicate check safer? ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] __attribute__((enable_if)) and non-overloaded member functions
+gbiv, would you be able to review this? On Sep 14, 2015 7:42 AM, "Ettore Speziale" wrote: > Ping > > > Gently ping. > > > >> On Aug 26, 2015, at 2:40 PM, Ettore Speziale > wrote: > >> > >> Forward to the right ML: > >> > Sorry about the extreme delay. This patch slipped through the cracks, > and I only noticed it again when searching my email for enable_if. > Committed in r245985! In the future, please feel free to continue pinging > weekly! > >>> > >>> NP, thank you for committing the patch. > >>> > >>> Unfortunately it contains a little error in the case of no candidate > has been found. For instance consider the following test case: > >>> > >>> struct Incomplete; > >>> > >>> struct X { > >>> void hidden_by_argument_conversion(Incomplete n, int m = 0) > __attribute((enable_if(m == 10, "chosen when 'm' is ten"))); > >>> }; > >>> > >>> x.hidden_by_argument_conversion(10); > >>> > >>> I would expect to get an error about Incomplete, as the compiler > cannot understand how to convert 10 into an instance of Incomplete. However > right now the enable_if diagnostic is emitted, thus masking the more useful > message about Incomplete. > >>> > >>> The attached patch solved the problem by delaying the point where the > enable_if diagnostic is issued. > >>> > >>> Thanks, > >>> Ettore Speziale > >> > >> > >> > > > > ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D13373: Emiting invariant.group.barrier for ctors bugfix
nlewycky added a comment. I can't meaningfully review this, but I see nothing wrong here. Comment at: lib/CodeGen/CGClass.cpp:1378 @@ -1377,3 +1377,3 @@ - bool BaseVPtrsInitialized = false; + llvm::Value* const OldThis = CXXThisValue; // Virtual base initializers first. "llvm::Value* const" --> "llvm::Value *const" http://reviews.llvm.org/D13373 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r244515 - If a variable template is inside a context with template arguments that is being instantiated, and that instantiation fails, fail our instantiation instead of crashing. Errors have already b
Author: nicholas Date: Mon Aug 10 16:54:08 2015 New Revision: 244515 URL: http://llvm.org/viewvc/llvm-project?rev=244515&view=rev Log: If a variable template is inside a context with template arguments that is being instantiated, and that instantiation fails, fail our instantiation instead of crashing. Errors have already been emitted. Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=244515&r1=244514&r2=244515&view=diff == --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Aug 10 16:54:08 2015 @@ -1143,6 +1143,7 @@ Decl *TemplateDeclInstantiator::VisitVar VarDecl *VarInst = cast_or_null(VisitVarDecl(Pattern, /*InstantiatingVarTemplate=*/true)); + if (!VarInst) return nullptr; DeclContext *DC = Owner; Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp?rev=244515&r1=244514&r2=244515&view=diff == --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp Mon Aug 10 16:54:08 2015 @@ -327,3 +327,14 @@ struct S { static int f : I; // expected-error {{static member 'f' cannot be a bit-field}} }; } + +namespace b20896909 { + // This used to crash. + template struct helper {}; + template class A { +template static helper x; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} + }; + void test() { +A ai; // expected-note {{in instantiation of}} + } +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
patch: clarify diagnostic when returned value doesn't match function return type
This simple-minded patch extends the case where we report "no viable conversion from 'X' to 'Y'" to emit a more useful diagnostic "no viable conversion from returned value of type 'X' to function return type 'Y'" when used in that context. In lieu of adding tests for this diagnostic explicitly, I've only updated the tests where the patch changes their result. Please review! Nick Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td (revision 244522) +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy) @@ -5788,7 +5788,8 @@ def err_typecheck_ambiguous_condition : Error< "conversion %diff{from $ to $|between types}0,1 is ambiguous">; def err_typecheck_nonviable_condition : Error< - "no viable conversion%diff{ from $ to $|}0,1">; + "no viable conversion%select{%diff{ from $ to $|}1,2|" + "%diff{ from returned value of type $ to function return type $|}1,2}0">; def err_typecheck_nonviable_condition_incomplete : Error< "no viable conversion%diff{ from $ to incomplete type $|}0,1">; def err_typecheck_deleted_function : Error< Index: lib/Sema/SemaInit.cpp === --- lib/Sema/SemaInit.cpp (revision 244522) +++ lib/Sema/SemaInit.cpp (working copy) @@ -6943,6 +6943,7 @@ diag::err_typecheck_nonviable_condition_incomplete, Args[0]->getType(), Args[0]->getSourceRange())) S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) + << (Entity.getKind() == InitializedEntity::EK_Result) << Args[0]->getType() << Args[0]->getSourceRange() << DestType.getNonReferenceType(); Index: lib/Sema/SemaOverload.cpp === --- lib/Sema/SemaOverload.cpp (revision 244522) +++ lib/Sema/SemaOverload.cpp (working copy) @@ -3212,7 +3212,7 @@ diag::err_typecheck_nonviable_condition_incomplete, From->getType(), From->getSourceRange())) Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition) - << From->getType() << From->getSourceRange() << ToType; + << false << From->getType() << From->getSourceRange() << ToType; } else return false; CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From); Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp === --- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp (revision 244522) +++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp (working copy) @@ -49,7 +49,7 @@ static double dfi(int i) { return i + 3.14; } static Local localfi(int) { return Local{}; } }; -auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from 'Local' to 'int'}} +auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from returned value of type 'Local' to function return type 'int'}} l4(&Local::ifi); l4(&Local::cfi); l4(&Local::dfi); Index: test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp === --- test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp (revision 244522) +++ test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp (working copy) @@ -38,7 +38,7 @@ template int infer_result(T x, T y) { auto lambda = [=](bool b) { return x + y; }; - return lambda(true); // expected-error{{no viable conversion from 'X' to 'int'}} + return lambda(true); // expected-error{{no viable conversion from returned value of type 'X' to function return type 'int'}} } template int infer_result(int, int); Index: test/SemaCXX/rval-references.cpp === --- test/SemaCXX/rval-references.cpp (revision 244522) +++ test/SemaCXX/rval-references.cpp (working copy) @@ -90,5 +90,5 @@ else if (0) // Copy from reference can't be elided return r; // expected-error {{call to deleted constructor}} else // Construction from different type can't be elided -return i; // expected-error {{no viable conversion from 'int' to 'MoveOnly'}} +return i; // expected-error {{no viable conversion from returned value of type 'int' to function return type 'MoveOnly'}} } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: patch: clarify diagnostic when returned value doesn't match function return type
On 10 August 2015 at 19:08, Nick Lewycky wrote: > This simple-minded patch extends the case where we report "no viable > conversion from 'X' to 'Y'" to emit a more useful diagnostic "no viable > conversion from returned value of type 'X' to function return type 'Y'" > when used in that context. > > In lieu of adding tests for this diagnostic explicitly, I've only updated > the tests where the patch changes their result. > > Please review! > Ping! ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: patch: clarify diagnostic when returned value doesn't match function return type
On 19 August 2015 at 15:18, Nick Lewycky wrote: > On 10 August 2015 at 19:08, Nick Lewycky wrote: > >> This simple-minded patch extends the case where we report "no viable >> conversion from 'X' to 'Y'" to emit a more useful diagnostic "no viable >> conversion from returned value of type 'X' to function return type 'Y'" >> when used in that context. >> >> In lieu of adding tests for this diagnostic explicitly, I've only updated >> the tests where the patch changes their result. >> >> Please review! >> > > Ping! > Ping! ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r245979 - Clarify the error message when the reason the conversion is not viable is because the returned value does not match the function return type.
Author: nicholas Date: Tue Aug 25 17:18:46 2015 New Revision: 245979 URL: http://llvm.org/viewvc/llvm-project?rev=245979&view=rev Log: Clarify the error message when the reason the conversion is not viable is because the returned value does not match the function return type. Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp cfe/trunk/test/SemaCXX/rval-references.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=245979&r1=245978&r2=245979&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Aug 25 17:18:46 2015 @@ -5792,7 +5792,8 @@ def err_typecheck_bool_condition : Error def err_typecheck_ambiguous_condition : Error< "conversion %diff{from $ to $|between types}0,1 is ambiguous">; def err_typecheck_nonviable_condition : Error< - "no viable conversion%diff{ from $ to $|}0,1">; + "no viable conversion%select{%diff{ from $ to $|}1,2|" + "%diff{ from returned value of type $ to function return type $|}1,2}0">; def err_typecheck_nonviable_condition_incomplete : Error< "no viable conversion%diff{ from $ to incomplete type $|}0,1">; def err_typecheck_deleted_function : Error< Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=245979&r1=245978&r2=245979&view=diff == --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Aug 25 17:18:46 2015 @@ -6946,6 +6946,7 @@ bool InitializationSequence::Diagnose(Se diag::err_typecheck_nonviable_condition_incomplete, Args[0]->getType(), Args[0]->getSourceRange())) S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) + << (Entity.getKind() == InitializedEntity::EK_Result) << Args[0]->getType() << Args[0]->getSourceRange() << DestType.getNonReferenceType(); Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=245979&r1=245978&r2=245979&view=diff == --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Aug 25 17:18:46 2015 @@ -3212,7 +3212,7 @@ Sema::DiagnoseMultipleUserDefinedConvers diag::err_typecheck_nonviable_condition_incomplete, From->getType(), From->getSourceRange())) Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition) - << From->getType() << From->getSourceRange() << ToType; + << false << From->getType() << From->getSourceRange() << ToType; } else return false; CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From); Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp?rev=245979&r1=245978&r2=245979&view=diff == --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp Tue Aug 25 17:18:46 2015 @@ -49,7 +49,7 @@ int main() static double dfi(int i) { return i + 3.14; } static Local localfi(int) { return Local{}; } }; -auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from 'Local' to 'int'}} +auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from returned value of type 'Local' to function return type 'int'}} l4(&Local::ifi); l4(&Local::cfi); l4(&Local::dfi); Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp?rev=245979&r1=245978&r2=245979&view=diff == --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp Tue Aug 25 17:18:46 2015 @@ -38,7 +38,7 @@ template X captures(X, X); template int infer_result(T x, T y) { auto lambda = [=](bo
r245985 - Make sure that we evaluate __attribute__((enable_if)) on a method with no overloads. Patch by Ettore Speziale!
Author: nicholas Date: Tue Aug 25 17:33:16 2015 New Revision: 245985 URL: http://llvm.org/viewvc/llvm-project?rev=245985&view=rev Log: Make sure that we evaluate __attribute__((enable_if)) on a method with no overloads. Patch by Ettore Speziale! Modified: cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/test/SemaCXX/enable_if.cpp Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=245985&r1=245984&r2=245985&view=diff == --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Aug 25 17:33:16 2015 @@ -5826,10 +5826,11 @@ EnableIfAttr *Sema::CheckEnableIf(Functi SFINAETrap Trap(*this); - // Convert the arguments. SmallVector ConvertedArgs; bool InitializationFailed = false; bool ContainsValueDependentExpr = false; + + // Convert the arguments. for (unsigned i = 0, e = Args.size(); i != e; ++i) { if (i == 0 && !MissingImplicitThis && isa(Function) && !cast(Function)->isStatic() && @@ -5863,6 +5864,28 @@ EnableIfAttr *Sema::CheckEnableIf(Functi if (InitializationFailed || Trap.hasErrorOccurred()) return cast(Attrs[0]); + // Push default arguments if needed. + if (!Function->isVariadic() && Args.size() < Function->getNumParams()) { +for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) { + ParmVarDecl *P = Function->getParamDecl(i); + ExprResult R = PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + Function->getParamDecl(i)), + SourceLocation(), + P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg() + : P->getDefaultArg()); + if (R.isInvalid()) { +InitializationFailed = true; +break; + } + ContainsValueDependentExpr |= R.get()->isValueDependent(); + ConvertedArgs.push_back(R.get()); +} + +if (InitializationFailed || Trap.hasErrorOccurred()) + return cast(Attrs[0]); + } + for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) { APValue Result; EnableIfAttr *EIA = cast(*I); @@ -11604,6 +11627,16 @@ Sema::BuildCallToMemberFunction(Scope *S FoundDecl = MemExpr->getFoundDecl(); Qualifier = MemExpr->getQualifier(); UnbridgedCasts.restore(); + +if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) { + Diag(MemExprE->getLocStart(), + diag::err_ovl_no_viable_member_function_in_call) + << Method << Method->getSourceRange(); + Diag(Method->getLocation(), + diag::note_ovl_candidate_disabled_by_enable_if_attr) + << Attr->getCond()->getSourceRange() << Attr->getMessage(); + return ExprError(); +} } else { UnresolvedMemberExpr *UnresExpr = cast(NakedMemExpr); Qualifier = UnresExpr->getQualifier(); Modified: cfe/trunk/test/SemaCXX/enable_if.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enable_if.cpp?rev=245985&r1=245984&r2=245985&view=diff == --- cfe/trunk/test/SemaCXX/enable_if.cpp (original) +++ cfe/trunk/test/SemaCXX/enable_if.cpp Tue Aug 25 17:33:16 2015 @@ -11,6 +11,10 @@ struct X { void f(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); void f(int n) __attribute__((enable_if(n == 1, "chosen when 'n' is one"))); // expected-note{{member declaration nearly matches}} expected-note{{candidate disabled: chosen when 'n' is one}} + void g(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); // expected-note{{candidate disabled: chosen when 'n' is zero}} + + void h(int n, int m = 0) __attribute((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}} + static void s(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); // expected-note2{{candidate disabled: chosen when 'n' is zero}} void conflict(int n) __attribute__((enable_if(n+n == 10, "chosen when 'n' is five"))); // expected-note{{candidate function}} @@ -40,6 +44,15 @@ void deprec2(int i) __attribute__((enabl void overloaded(int); void overloaded(long); +struct Int { + constexpr Int(int i) : i(i) { } + constexpr operator int() const { return i; } + int i; +}; + +void default_argument(int n, int m = 0) __attribute__((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}} +void default_argument_promotion(int n, int m = Int(0)) __attribute__((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}} + struct Nothing { }; template void typedep(T t) __attribute__((enable_if(t, ""))); // expected-note{{candidate disabled:}}
Fwd: [PATCH] __attribute__((enable_if)) and non-overloaded member functions
--> lists.llvm.org -- Forwarded message -- From: Ettore Speziale Date: 26 August 2015 at 14:35 Subject: Re: [PATCH] __attribute__((enable_if)) and non-overloaded member functions To: Nick Lewycky Cc: llvm cfe Hello, > Sorry about the extreme delay. This patch slipped through the cracks, and I only noticed it again when searching my email for enable_if. Committed in r245985! In the future, please feel free to continue pinging weekly! NP, thank you for committing the patch. Unfortunately it contains a little error in the case of no candidate has been found. For instance consider the following test case: struct Incomplete; struct X { void hidden_by_argument_conversion(Incomplete n, int m = 0) __attribute((enable_if(m == 10, "chosen when 'm' is ten"))); }; x.hidden_by_argument_conversion(10); I would expect to get an error about Incomplete, as the compiler cannot understand how to convert 10 into an instance of Incomplete. However right now the enable_if diagnostic is emitted, thus masking the more useful message about Incomplete. The attached patch solved the problem by delaying the point where the enable_if diagnostic is issued. Thanks, Ettore Speziale enable_if.diff Description: Binary data ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r250666 - No functionality change, just fix whitespace, a typo and remove an unnecessary
Author: nicholas Date: Sun Oct 18 15:32:12 2015 New Revision: 250666 URL: http://llvm.org/viewvc/llvm-project?rev=250666&view=rev Log: No functionality change, just fix whitespace, a typo and remove an unnecessary emacs mode marker. (Changes left behind from another patch that ended up not working out.) Modified: cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=250666&r1=250665&r2=250666&view=diff == --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Sun Oct 18 15:32:12 2015 @@ -1233,7 +1233,7 @@ void DeclContext::addHiddenDecl(Decl *D) } // Notify a C++ record declaration that we've added a member, so it can - // update it's class-specific state. + // update its class-specific state. if (CXXRecordDecl *Record = dyn_cast(this)) Record->addedMember(D); Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=250666&r1=250665&r2=250666&view=diff == --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Sun Oct 18 15:32:12 2015 @@ -1,4 +1,4 @@ -//===- SemaLookup.cpp - Name Lookup *- C++ -*-===// +//===- SemaLookup.cpp - Name Lookup --===// // // The LLVM Compiler Infrastructure // @@ -154,7 +154,7 @@ namespace { // by its using directives, transitively) as if they appeared in // the given effective context. void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) { - SmallVector queue; + SmallVector queue; while (true) { for (auto UD : DC->using_directives()) { DeclContext *NS = UD->getNominatedNamespace(); @@ -2189,7 +2189,7 @@ void Sema::DiagnoseAmbiguousLookup(Looku case LookupResult::AmbiguousTagHiding: { Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange; -llvm::SmallPtrSet TagDecls; +llvm::SmallPtrSet TagDecls; for (auto *D : Result) if (TagDecl *TD = dyn_cast(D)) { Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=250666&r1=250665&r2=250666&view=diff == --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Sun Oct 18 15:32:12 2015 @@ -260,7 +260,7 @@ void ASTDeclWriter::Visit(Decl *D) { // Source locations require array (variable-length) abbreviations. The // abbreviation infrastructure requires that arrays are encoded last, so // we handle it here in the case of those classes derived from DeclaratorDecl - if (DeclaratorDecl *DD = dyn_cast(D)){ + if (DeclaratorDecl *DD = dyn_cast(D)) { Writer.AddTypeSourceInfo(DD->getTypeSourceInfo(), Record); } @@ -2101,7 +2101,7 @@ void ASTWriter::WriteDecl(ASTContext &Co if (IDR == 0) IDR = NextDeclID++; -ID= IDR; +ID = IDR; } bool isReplacingADecl = ID < FirstDeclID; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r244490 - Fix typo.
Author: nicholas Date: Mon Aug 10 14:54:11 2015 New Revision: 244490 URL: http://llvm.org/viewvc/llvm-project?rev=244490&view=rev Log: Fix typo. Modified: cfe/trunk/docs/LanguageExtensions.rst Modified: cfe/trunk/docs/LanguageExtensions.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=244490&r1=244489&r2=244490&view=diff == --- cfe/trunk/docs/LanguageExtensions.rst (original) +++ cfe/trunk/docs/LanguageExtensions.rst Mon Aug 10 14:54:11 2015 @@ -415,7 +415,7 @@ dash indicates that an operation is not specification. == === === === === - Opeator OpenCL AltiVec GCCNEON + Operator OpenCL AltiVec GCCNEON == === === === === [] yes yes yes -- unary operators +, --yes yes yes -- ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D22900: Revert r244207 - Mark calls in thunk functions as tail-call optimization
nlewycky added a comment. For the IR level, I think this has got to be valid: declare void @bar(i32* byval %p) define void @foo(i32* byval %p) { tail call void @bar(i32* byval %p.tmp) ret void } The `tail` is an aliasing property which indicates that the callee doesn't touch any of the alloca's in the caller, a rough proxy for "stack" since there is no other stack in LLVM IR. That doesn't mean that we're going to actually lower it to a tail call in the final assembly, but if we don't put `tail` on a call, we won't even consider it for becoming a tail call. I think the backend can sort out whether the byval is going to lead to a stack allocation in @foo and emit a non-tail call if so. https://reviews.llvm.org/D22900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D19586: Misleading Indentation check
nlewycky added a subscriber: nlewycky. Comment at: clang-tidy/readability/MisleadingIndentationCheck.cpp:31 @@ +30,3 @@ + Result.SourceManager->getExpansionColumnNumber(ElseLoc)) +diag(ElseLoc, "potentional dangling else"); +} Typo of "potential" as "potentional". Comment at: clang-tidy/readability/MisleadingIndentationCheck.cpp:54 @@ +53,3 @@ + +if (Result.SourceManager->getExpansionColumnNumber(StmtLoc) == +Result.SourceManager->getExpansionColumnNumber(NextLoc)) What about a one-line "if (x) foo(); else bar();"? Warn on it anyways? Comment at: clang-tidy/readability/MisleadingIndentationCheck.cpp:56 @@ +55,3 @@ +Result.SourceManager->getExpansionColumnNumber(NextLoc)) + diag(NextLoc, "Wrong Indentation - statement is indentated as a member " +"of if statement"); Typo of "indented" as "indentated". Comment at: test/clang-tidy/readability-misleading-indentation.cpp:48 @@ +47,3 @@ + } + foo2(); // ok + This is arguably misleading indentation, but I'm ok with not warning on it if you think it will cause too many false positives. http://reviews.llvm.org/D19586 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D19851: Warn on binding reference to null in copy initialization
nicholas created this revision. nicholas added a reviewer: cfe-commits. The attached patch adds a warning when placing a call like: func(*static_cast(nullptr)); to the existing -Wnull-dereference warning. The existing warning catches the case where the empty lvalue undergoes lvalue-to-rvalue conversion. The attached patch adds the check when it is used for copy initialization. There's some significant opportunity for refactoring with the static CheckForNullPointerDereference function in SemaExpr.cpp (not to be confused with the one I'm adding to SemaInit.cpp). Also, I've chosen different warning text since all cases where the existing warning fires get compiled to nothing, while cases where this warning fires may generate object code (creating "null references" usually). Please review! http://reviews.llvm.org/D19851 Files: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaInit.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp test/Parser/cxx-casting.cpp Index: test/Parser/cxx-casting.cpp === --- test/Parser/cxx-casting.cpp +++ test/Parser/cxx-casting.cpp @@ -37,7 +37,7 @@ // This was being incorrectly tentatively parsed. namespace test1 { template class A {}; // expected-note 2{{here}} - void foo() { A(*(A*)0); } + void foo() { A(*(A*)0); } // expected-warning {{binding null pointer to reference has undefined behavior}} } typedef char* c; Index: test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp === --- test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp +++ test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -11,7 +11,7 @@ template struct bogus_override_if_virtual : public T { - bogus_override_if_virtual() : T(*(T*)0) { } + bogus_override_if_virtual() : T(*(T*)0) { } // expected-warning {{binding null pointer to reference has undefined behavior}} int operator()() const; }; @@ -36,7 +36,7 @@ lv(); // expected-error{{no matching function for call to object of type}} mlv(); // expected-error{{no matching function for call to object of type}} - bogus_override_if_virtual bogus; + bogus_override_if_virtual bogus; // expected-note{{in instantiation of member function 'bogus_override_if_virtual<(lambda}} } // Core issue 974: default arguments (8.3.6) may be specified in the Index: lib/Sema/SemaInit.cpp === --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -3510,6 +3510,23 @@ return CandidateSet.BestViableFunction(S, DeclLoc, Best); } +static void CheckForNullPointerDereference(Sema &S, Expr *E) { + // Check to see if we are dereferencing a null pointer. If so, + // and if not volatile-qualified, this is undefined behavior that the + // optimizer will delete, so warn about it. People sometimes try to use this + // to get a deterministic trap and are surprised by clang's behavior. This + // only handles the pattern "*null", which is a very syntactic check. + if (UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) +if (UO->getOpcode() == UO_Deref && +UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) && +!UO->getType().isVolatileQualified()) { +S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::warn_binding_null_to_reference) +<< UO->getSubExpr()->getSourceRange()); + } +} + /// \brief Attempt initialization by constructor (C++ [dcl.init]), which /// enumerates the constructors of the initialized entity and performs overload /// resolution to select the best. @@ -3629,6 +3646,10 @@ return; } + for (Expr *Arg : Args) { +CheckForNullPointerDereference(S, Arg); + } + // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. bool HadMultipleCandidates = (CandidateSet.size() > 1); Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5359,6 +5359,8 @@ InGroup>; def warn_indirection_through_null : Warning< "indirection of non-volatile null pointer will be deleted, not trap">, InGroup; +def warn_binding_null_to_reference : Warning< + "binding null pointer to reference has undefined behavior">, InGroup; def note_indirection_through_null : Note< "consider using __builtin_trap() or qualifying pointer with 'volatile'">; def warn_pointer_indirection_from_incompatible_type : Warning< Index: test/Parser/cxx-casting.cpp === --- test/Parser/cxx-casting.cpp +++ test/Parser/cxx-casting.cpp @@ -37,7 +37,7 @@ // This was being incorrectly tentatively parsed. namespace test1 { temp
Re: [PATCH] D19851: Warn on binding reference to null in copy initialization
nicholas marked 2 inline comments as done. nicholas added a comment. Richard Smith gave me some review feedback in person, the diagnostic should not be generated when setting up the Steps for the initializer sequence, but instead when InitializerSequence::Perform is called. This appears to work correctly and also catches a few more cases. I did not expand this to SK_BindReferenceToTemporary, please review this decision. It's also missing missing bit-field and vector element checks that SK_BindReference has. Also, I'd appreciate comments on the factoring with CheckForNullPointerDereference which was copied+pasted from SemaExpr.cpp. Please review this issue too, I did not expect to land the patch the way it's currently written. Comment at: test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp:39 @@ -38,3 +38,3 @@ - bogus_override_if_virtual bogus; + bogus_override_if_virtual bogus; // expected-note{{in instantiation of member function 'bogus_override_if_virtual<(lambda}} } aaron.ballman wrote: > Missing `>` in the diagnostic text (I know it's not required, but it looks a > bit strange if that's the only part missing from the diagnostic text). What follows lambda is the path to the file, then the closing )>. I'd rather not include that part. I could make it up with .* just to balance the parens, but I think that's not worth it. http://reviews.llvm.org/D19851 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D19851: Warn on binding reference to null in copy initialization
nicholas updated this revision to Diff 56100. http://reviews.llvm.org/D19851 Files: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaInit.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp test/Parser/cxx-casting.cpp test/SemaCXX/cstyle-cast.cpp test/SemaCXX/functional-cast.cpp test/SemaCXX/new-delete.cpp test/SemaCXX/static-cast.cpp Index: test/SemaCXX/static-cast.cpp === --- test/SemaCXX/static-cast.cpp +++ test/SemaCXX/static-cast.cpp @@ -43,11 +43,11 @@ (void)static_cast((int*)0); (void)static_cast((const int*)0); (void)static_cast((B*)0); - (void)static_cast(*((B*)0)); + (void)static_cast(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((C1*)0); - (void)static_cast(*((C1*)0)); + (void)static_cast(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((D*)0); - (void)static_cast(*((D*)0)); + (void)static_cast(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((int A::*)0); (void)static_cast((void (A::*)())0); Index: test/SemaCXX/new-delete.cpp === --- test/SemaCXX/new-delete.cpp +++ test/SemaCXX/new-delete.cpp @@ -444,11 +444,11 @@ template void tfn() { -new (*(PlacementArg*)0) T[1]; +new (*(PlacementArg*)0) T[1]; // expected-warning 2 {{binding null pointer to reference has undefined behavior}} } void fn() { -tfn(); +tfn(); // expected-note {{in instantiation of function template specialization 'r150682::tfn' requested here}} } } Index: test/SemaCXX/functional-cast.cpp === --- test/SemaCXX/functional-cast.cpp +++ test/SemaCXX/functional-cast.cpp @@ -126,14 +126,14 @@ typedef A *Ap; (void)Ap((B*)0); typedef A &Ar; - (void)Ar(*((B*)0)); + (void)Ar(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef const B *cBp; (void)cBp((C1*)0); typedef B &Br; - (void)Br(*((C1*)0)); + (void)Br(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)Ap((D*)0); typedef const A &cAr; - (void)cAr(*((D*)0)); + (void)cAr(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef int B::*Bmp; (void)Bmp((int A::*)0); typedef void (B::*Bmfp)(); Index: test/SemaCXX/cstyle-cast.cpp === --- test/SemaCXX/cstyle-cast.cpp +++ test/SemaCXX/cstyle-cast.cpp @@ -84,11 +84,11 @@ (void)(void*)((int*)0); (void)(volatile const void*)((const int*)0); (void)(A*)((B*)0); - (void)(A&)(*((B*)0)); + (void)(A&)(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(const B*)((C1*)0); - (void)(B&)(*((C1*)0)); + (void)(B&)(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(A*)((D*)0); - (void)(const A&)(*((D*)0)); + (void)(const A&)(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(int B::*)((int A::*)0); (void)(void (B::*)())((void (A::*)())0); (void)(A*)((E*)0); // C-style cast ignores access control Index: test/Parser/cxx-casting.cpp === --- test/Parser/cxx-casting.cpp +++ test/Parser/cxx-casting.cpp @@ -37,7 +37,7 @@ // This was being incorrectly tentatively parsed. namespace test1 { template class A {}; // expected-note 2{{here}} - void foo() { A(*(A*)0); } + void foo() { A(*(A*)0); } // expected-warning {{binding null pointer to reference has undefined behavior}} } typedef char* c; Index: test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp === --- test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp +++ test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -11,7 +11,7 @@ template struct bogus_override_if_virtual : public T { - bogus_override_if_virtual() : T(*(T*)0) { } + bogus_override_if_virtual() : T(*(T*)0) { } // expected-warning {{binding null pointer to reference has undefined behavior}} int operator()() const; }; @@ -36,7 +36,7 @@ lv(); // expected-error{{no matching function for call to object of type}} mlv(); // expected-error{{no matching function for call to object of type}} - bogus_override_if_virtual bogus; + bogus_override_if_virtual bogus; // expected-note{{in instantiation of member function 'bogus_override_if_virtual<(lambda}} } // Core issue 974: default arguments (8.3.6) may be specified in the Index: lib/Sema/SemaInit.cpp === --- lib/Sema/SemaInit.cpp +++
Re: [PATCH] D19851: Warn on binding reference to null in copy initialization
nicholas marked 2 inline comments as done. Comment at: lib/Sema/SemaInit.cpp:3514-3518 @@ +3513,7 @@ +static void CheckForNullPointerDereference(Sema &S, const Expr *E) { + // Check to see if we are dereferencing a null pointer. If so, + // and if not volatile-qualified, this is undefined behavior that the + // optimizer will delete, so warn about it. People sometimes try to use this + // to get a deterministic trap and are surprised by clang's behavior. This + // only handles the pattern "*null", which is a very syntactic check. + if (const UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) rsmith wrote: > This comment doesn't make sense for this case. Binding a reference to a > dereferenced null pointer isn't something that people would expect to trap. > But the idea is the same: we might delete people's code and they're probably > not expecting that. We don't delete it, generally we "create a null reference" which is exactly what some programmers expect, when they think that references are just syntactically different pointers. Comment at: lib/Sema/SemaInit.cpp:3519-3522 @@ +3518,6 @@ + // only handles the pattern "*null", which is a very syntactic check. + if (const UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) +if (UO->getOpcode() == UO_Deref && +UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) && +!UO->getType().isVolatileQualified()) { rsmith wrote: > It seems -- borderline -- worth factoring out these four lines between here > and SemaExpr. Maybe `isProvablyEmptyLvalue` or similar, if you feel inclined > to do so? I'll pass. Initially I thought the two CheckForNullPointerDereference functions might be the same but for a diag::ID argument, but they're growing more and more different. As for `isProvablyEmptyLvalue` we would still need to get the UO for the diagnostic anyways. http://reviews.llvm.org/D19851 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D19851: Warn on binding reference to null in copy initialization
nicholas updated this revision to Diff 56235. nicholas marked an inline comment as done. http://reviews.llvm.org/D19851 Files: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaInit.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp test/Parser/cxx-casting.cpp test/SemaCXX/cstyle-cast.cpp test/SemaCXX/functional-cast.cpp test/SemaCXX/new-delete.cpp test/SemaCXX/static-cast.cpp Index: test/SemaCXX/static-cast.cpp === --- test/SemaCXX/static-cast.cpp +++ test/SemaCXX/static-cast.cpp @@ -43,11 +43,11 @@ (void)static_cast((int*)0); (void)static_cast((const int*)0); (void)static_cast((B*)0); - (void)static_cast(*((B*)0)); + (void)static_cast(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((C1*)0); - (void)static_cast(*((C1*)0)); + (void)static_cast(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((D*)0); - (void)static_cast(*((D*)0)); + (void)static_cast(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((int A::*)0); (void)static_cast((void (A::*)())0); Index: test/SemaCXX/new-delete.cpp === --- test/SemaCXX/new-delete.cpp +++ test/SemaCXX/new-delete.cpp @@ -444,11 +444,11 @@ template void tfn() { -new (*(PlacementArg*)0) T[1]; +new (*(PlacementArg*)0) T[1]; // expected-warning 2 {{binding null pointer to reference has undefined behavior}} } void fn() { -tfn(); +tfn(); // expected-note {{in instantiation of function template specialization 'r150682::tfn' requested here}} } } Index: test/SemaCXX/functional-cast.cpp === --- test/SemaCXX/functional-cast.cpp +++ test/SemaCXX/functional-cast.cpp @@ -126,14 +126,14 @@ typedef A *Ap; (void)Ap((B*)0); typedef A &Ar; - (void)Ar(*((B*)0)); + (void)Ar(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef const B *cBp; (void)cBp((C1*)0); typedef B &Br; - (void)Br(*((C1*)0)); + (void)Br(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)Ap((D*)0); typedef const A &cAr; - (void)cAr(*((D*)0)); + (void)cAr(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef int B::*Bmp; (void)Bmp((int A::*)0); typedef void (B::*Bmfp)(); Index: test/SemaCXX/cstyle-cast.cpp === --- test/SemaCXX/cstyle-cast.cpp +++ test/SemaCXX/cstyle-cast.cpp @@ -84,11 +84,11 @@ (void)(void*)((int*)0); (void)(volatile const void*)((const int*)0); (void)(A*)((B*)0); - (void)(A&)(*((B*)0)); + (void)(A&)(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(const B*)((C1*)0); - (void)(B&)(*((C1*)0)); + (void)(B&)(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(A*)((D*)0); - (void)(const A&)(*((D*)0)); + (void)(const A&)(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(int B::*)((int A::*)0); (void)(void (B::*)())((void (A::*)())0); (void)(A*)((E*)0); // C-style cast ignores access control Index: test/Parser/cxx-casting.cpp === --- test/Parser/cxx-casting.cpp +++ test/Parser/cxx-casting.cpp @@ -37,7 +37,7 @@ // This was being incorrectly tentatively parsed. namespace test1 { template class A {}; // expected-note 2{{here}} - void foo() { A(*(A*)0); } + void foo() { A(*(A*)0); } // expected-warning {{binding null pointer to reference has undefined behavior}} } typedef char* c; Index: test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp === --- test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp +++ test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -11,7 +11,7 @@ template struct bogus_override_if_virtual : public T { - bogus_override_if_virtual() : T(*(T*)0) { } + bogus_override_if_virtual() : T(*(T*)0) { } // expected-warning {{binding null pointer to reference has undefined behavior}} int operator()() const; }; @@ -36,7 +36,7 @@ lv(); // expected-error{{no matching function for call to object of type}} mlv(); // expected-error{{no matching function for call to object of type}} - bogus_override_if_virtual bogus; + bogus_override_if_virtual bogus; // expected-note{{in instantiation of member function 'bogus_override_if_virtual<(lambda}} } // Core issue 974: default arguments (8.3.6) may be specified in the Index: lib/Sema/SemaInit.cpp ===
Re: [PATCH] D19851: Warn on binding reference to null in copy initialization
nicholas updated this revision to Diff 56236. nicholas added a comment. (Whoops, forgot to generate diff with full context for phab.) http://reviews.llvm.org/D19851 Files: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaInit.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp test/Parser/cxx-casting.cpp test/SemaCXX/cstyle-cast.cpp test/SemaCXX/functional-cast.cpp test/SemaCXX/new-delete.cpp test/SemaCXX/static-cast.cpp Index: test/SemaCXX/static-cast.cpp === --- test/SemaCXX/static-cast.cpp +++ test/SemaCXX/static-cast.cpp @@ -43,11 +43,11 @@ (void)static_cast((int*)0); (void)static_cast((const int*)0); (void)static_cast((B*)0); - (void)static_cast(*((B*)0)); + (void)static_cast(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((C1*)0); - (void)static_cast(*((C1*)0)); + (void)static_cast(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((D*)0); - (void)static_cast(*((D*)0)); + (void)static_cast(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((int A::*)0); (void)static_cast((void (A::*)())0); Index: test/SemaCXX/new-delete.cpp === --- test/SemaCXX/new-delete.cpp +++ test/SemaCXX/new-delete.cpp @@ -444,11 +444,11 @@ template void tfn() { -new (*(PlacementArg*)0) T[1]; +new (*(PlacementArg*)0) T[1]; // expected-warning 2 {{binding null pointer to reference has undefined behavior}} } void fn() { -tfn(); +tfn(); // expected-note {{in instantiation of function template specialization 'r150682::tfn' requested here}} } } Index: test/SemaCXX/functional-cast.cpp === --- test/SemaCXX/functional-cast.cpp +++ test/SemaCXX/functional-cast.cpp @@ -126,14 +126,14 @@ typedef A *Ap; (void)Ap((B*)0); typedef A &Ar; - (void)Ar(*((B*)0)); + (void)Ar(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef const B *cBp; (void)cBp((C1*)0); typedef B &Br; - (void)Br(*((C1*)0)); + (void)Br(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)Ap((D*)0); typedef const A &cAr; - (void)cAr(*((D*)0)); + (void)cAr(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef int B::*Bmp; (void)Bmp((int A::*)0); typedef void (B::*Bmfp)(); Index: test/SemaCXX/cstyle-cast.cpp === --- test/SemaCXX/cstyle-cast.cpp +++ test/SemaCXX/cstyle-cast.cpp @@ -84,11 +84,11 @@ (void)(void*)((int*)0); (void)(volatile const void*)((const int*)0); (void)(A*)((B*)0); - (void)(A&)(*((B*)0)); + (void)(A&)(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(const B*)((C1*)0); - (void)(B&)(*((C1*)0)); + (void)(B&)(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(A*)((D*)0); - (void)(const A&)(*((D*)0)); + (void)(const A&)(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(int B::*)((int A::*)0); (void)(void (B::*)())((void (A::*)())0); (void)(A*)((E*)0); // C-style cast ignores access control Index: test/Parser/cxx-casting.cpp === --- test/Parser/cxx-casting.cpp +++ test/Parser/cxx-casting.cpp @@ -37,7 +37,7 @@ // This was being incorrectly tentatively parsed. namespace test1 { template class A {}; // expected-note 2{{here}} - void foo() { A(*(A*)0); } + void foo() { A(*(A*)0); } // expected-warning {{binding null pointer to reference has undefined behavior}} } typedef char* c; Index: test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp === --- test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp +++ test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -11,7 +11,7 @@ template struct bogus_override_if_virtual : public T { - bogus_override_if_virtual() : T(*(T*)0) { } + bogus_override_if_virtual() : T(*(T*)0) { } // expected-warning {{binding null pointer to reference has undefined behavior}} int operator()() const; }; @@ -36,7 +36,7 @@ lv(); // expected-error{{no matching function for call to object of type}} mlv(); // expected-error{{no matching function for call to object of type}} - bogus_override_if_virtual bogus; + bogus_override_if_virtual bogus; // expected-note{{in instantiation of member function 'bogus_override_if_virtual<(lambda}} } // Core issue 974: default arguments (8.3.6) may be specified in the Index: lib/Sema/SemaInit.cpp
Re: [PATCH] D19851: Warn on binding reference to null in copy initialization
nicholas updated this revision to Diff 56526. nicholas added a comment. Unsure why, but the previous diff didn't have the 'volatile' check removed. http://reviews.llvm.org/D19851 Files: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaInit.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp test/Parser/cxx-casting.cpp test/SemaCXX/cstyle-cast.cpp test/SemaCXX/functional-cast.cpp test/SemaCXX/new-delete.cpp test/SemaCXX/static-cast.cpp Index: test/SemaCXX/static-cast.cpp === --- test/SemaCXX/static-cast.cpp +++ test/SemaCXX/static-cast.cpp @@ -43,11 +43,11 @@ (void)static_cast((int*)0); (void)static_cast((const int*)0); (void)static_cast((B*)0); - (void)static_cast(*((B*)0)); + (void)static_cast(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((C1*)0); - (void)static_cast(*((C1*)0)); + (void)static_cast(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((D*)0); - (void)static_cast(*((D*)0)); + (void)static_cast(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((int A::*)0); (void)static_cast((void (A::*)())0); Index: test/SemaCXX/new-delete.cpp === --- test/SemaCXX/new-delete.cpp +++ test/SemaCXX/new-delete.cpp @@ -444,11 +444,11 @@ template void tfn() { -new (*(PlacementArg*)0) T[1]; +new (*(PlacementArg*)0) T[1]; // expected-warning 2 {{binding null pointer to reference has undefined behavior}} } void fn() { -tfn(); +tfn(); // expected-note {{in instantiation of function template specialization 'r150682::tfn' requested here}} } } Index: test/SemaCXX/functional-cast.cpp === --- test/SemaCXX/functional-cast.cpp +++ test/SemaCXX/functional-cast.cpp @@ -126,14 +126,14 @@ typedef A *Ap; (void)Ap((B*)0); typedef A &Ar; - (void)Ar(*((B*)0)); + (void)Ar(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef const B *cBp; (void)cBp((C1*)0); typedef B &Br; - (void)Br(*((C1*)0)); + (void)Br(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)Ap((D*)0); typedef const A &cAr; - (void)cAr(*((D*)0)); + (void)cAr(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef int B::*Bmp; (void)Bmp((int A::*)0); typedef void (B::*Bmfp)(); Index: test/SemaCXX/cstyle-cast.cpp === --- test/SemaCXX/cstyle-cast.cpp +++ test/SemaCXX/cstyle-cast.cpp @@ -84,11 +84,11 @@ (void)(void*)((int*)0); (void)(volatile const void*)((const int*)0); (void)(A*)((B*)0); - (void)(A&)(*((B*)0)); + (void)(A&)(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(const B*)((C1*)0); - (void)(B&)(*((C1*)0)); + (void)(B&)(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(A*)((D*)0); - (void)(const A&)(*((D*)0)); + (void)(const A&)(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(int B::*)((int A::*)0); (void)(void (B::*)())((void (A::*)())0); (void)(A*)((E*)0); // C-style cast ignores access control Index: test/Parser/cxx-casting.cpp === --- test/Parser/cxx-casting.cpp +++ test/Parser/cxx-casting.cpp @@ -37,7 +37,7 @@ // This was being incorrectly tentatively parsed. namespace test1 { template class A {}; // expected-note 2{{here}} - void foo() { A(*(A*)0); } + void foo() { A(*(A*)0); } // expected-warning {{binding null pointer to reference has undefined behavior}} } typedef char* c; Index: test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp === --- test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp +++ test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -11,7 +11,7 @@ template struct bogus_override_if_virtual : public T { - bogus_override_if_virtual() : T(*(T*)0) { } + bogus_override_if_virtual() : T(*(T*)0) { } // expected-warning {{binding null pointer to reference has undefined behavior}} int operator()() const; }; @@ -36,7 +36,7 @@ lv(); // expected-error{{no matching function for call to object of type}} mlv(); // expected-error{{no matching function for call to object of type}} - bogus_override_if_virtual bogus; + bogus_override_if_virtual bogus; // expected-note{{in instantiation of member function 'bogus_override_if_virtual<(lambda}} } // Core issue 974: default arguments (8.3.6) may be specified in the Index: lib/Sema/SemaIni
r269572 - Warn when a reference is bound to an empty l-value (dereferenced null pointer).
Author: nicholas Date: Sat May 14 12:44:14 2016 New Revision: 269572 URL: http://llvm.org/viewvc/llvm-project?rev=269572&view=rev Log: Warn when a reference is bound to an empty l-value (dereferenced null pointer). Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp cfe/trunk/test/Parser/cxx-casting.cpp cfe/trunk/test/SemaCXX/cstyle-cast.cpp cfe/trunk/test/SemaCXX/functional-cast.cpp cfe/trunk/test/SemaCXX/new-delete.cpp cfe/trunk/test/SemaCXX/static-cast.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=269572&r1=269571&r2=269572&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat May 14 12:44:14 2016 @@ -5371,7 +5371,11 @@ def ext_typecheck_indirection_through_vo "ISO C++ does not allow indirection on operand of type %0">, InGroup>; def warn_indirection_through_null : Warning< - "indirection of non-volatile null pointer will be deleted, not trap">, InGroup; + "indirection of non-volatile null pointer will be deleted, not trap">, + InGroup; +def warn_binding_null_to_reference : Warning< + "binding dereferenced null pointer to reference has undefined behavior">, + InGroup; def note_indirection_through_null : Note< "consider using __builtin_trap() or qualifying pointer with 'volatile'">; def warn_pointer_indirection_from_incompatible_type : Warning< Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=269572&r1=269571&r2=269572&view=diff == --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Sat May 14 12:44:14 2016 @@ -6168,6 +6168,20 @@ static void CheckMoveOnConstruction(Sema << FixItHint::CreateRemoval(SourceRange(RParen, RParen)); } +static void CheckForNullPointerDereference(Sema &S, const Expr *E) { + // Check to see if we are dereferencing a null pointer. If so, this is + // undefined behavior, so warn about it. This only handles the pattern + // "*null", which is a very syntactic check. + if (const UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) +if (UO->getOpcode() == UO_Deref && +UO->getSubExpr()->IgnoreParenCasts()-> +isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) { +S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::warn_binding_null_to_reference) +<< UO->getSubExpr()->getSourceRange()); + } +} + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -6420,6 +6434,7 @@ InitializationSequence::Perform(Sema &S, /*IsInitializerList=*/false, ExtendingEntity->getDecl()); + CheckForNullPointerDereference(S, CurInit.get()); break; case SK_BindReferenceToTemporary: { Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp?rev=269572&r1=269571&r2=269572&view=diff == --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp (original) +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp Sat May 14 12:44:14 2016 @@ -11,7 +11,7 @@ void test_attributes() { template struct bogus_override_if_virtual : public T { - bogus_override_if_virtual() : T(*(T*)0) { } + bogus_override_if_virtual() : T(*(T*)0) { } // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}} int operator()() const; }; @@ -36,7 +36,7 @@ void test_quals() { lv(); // expected-error{{no matching function for call to object of type}} mlv(); // expected-error{{no matching function for call to object of type}} - bogus_override_if_virtual bogus; + bogus_override_if_virtual bogus; // expected-note{{in instantiation of member function 'bogus_override_if_virtual<(lambda}} } // Core issue 974: default arguments (8.3.6) may be specified in the Modified: cfe/trunk/test/Parser/cxx-casting.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-casting.cpp?rev=269572&r1=269571&r2=269572&view=diff == --- cfe/trunk/test/Parser/cxx-casting.cpp (original) +++ cfe/trunk/test/Parser/cxx-casting.cpp Sat May 14 12:44:14 2016 @@ -37,7 +37,7 @@ char postfix_expr_test() // This was being incorrectly tentatively parsed. namesp
Re: [PATCH] D19851: Warn on binding reference to null in copy initialization
nicholas closed this revision. nicholas added a comment. Closed by r269572. http://reviews.llvm.org/D19851 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r269625 - Make this SourceLocation getter const LLVM_READONLY like others in the same file.
Author: nicholas Date: Sun May 15 21:46:07 2016 New Revision: 269625 URL: http://llvm.org/viewvc/llvm-project?rev=269625&view=rev Log: Make this SourceLocation getter const LLVM_READONLY like others in the same file. Modified: cfe/trunk/include/clang/AST/StmtObjC.h Modified: cfe/trunk/include/clang/AST/StmtObjC.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtObjC.h?rev=269625&r1=269624&r2=269625&view=diff == --- cfe/trunk/include/clang/AST/StmtObjC.h (original) +++ cfe/trunk/include/clang/AST/StmtObjC.h Sun May 15 21:46:07 2016 @@ -326,7 +326,7 @@ public: Expr *getThrowExpr() { return reinterpret_cast(Throw); } void setThrowExpr(Stmt *S) { Throw = S; } - SourceLocation getThrowLoc() { return AtThrowLoc; } + SourceLocation getThrowLoc() const LLVM_READONLY { return AtThrowLoc; } void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: r269572 - Warn when a reference is bound to an empty l-value (dereferenced null pointer).
Hans Wennborg wrote: On Sat, May 14, 2016 at 10:44 AM, Nick Lewycky via cfe-commits wrote: Author: nicholas Date: Sat May 14 12:44:14 2016 New Revision: 269572 URL: http://llvm.org/viewvc/llvm-project?rev=269572&view=rev Log: Warn when a reference is bound to an empty l-value (dereferenced null pointer). Could this be made to handle return values too? The warning fired on some code in pdfium, and nearby I found this: TYPE& ElementAt(int nIndex) { if (nIndex< 0 || nIndex>= m_nSize) { return *(TYPE*)NULL;<-- Ooops } return ((TYPE*)m_pData)[nIndex]; } where the warning doesn't fire. That looks like a bug, we should already catch that case: int &test1() { return *(int*)nullptr; } struct TYPE {}; TYPE &test2() { return *(TYPE*)nullptr; } clang ref.cc -std=c++11 ref.cc:2:10: warning: binding dereferenced null pointer to reference has undefined behavior [-Wnull-dereference] return *(int*)nullptr; ^~ ref.cc:6:10: warning: binding dereferenced null pointer to reference has undefined behavior [-Wnull-dereference] return *(TYPE*)nullptr; ^~~ 2 warnings generated. Could you produce a testcase for it? Nick ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D21352: Add a "declared 'nonnull' here" note to warnings where an expression is checked against null.
nlewycky created this revision. nlewycky added a subscriber: cfe-commits. Point to the relevant 'nonnull' or 'returns_nonnull' attribute when complaining about 'a == 0' or 'f() == 0' expressions. http://reviews.llvm.org/D21352 Files: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaChecking.cpp test/Sema/nonnull.c Index: test/Sema/nonnull.c === --- test/Sema/nonnull.c +++ test/Sema/nonnull.c @@ -86,7 +86,7 @@ // rdar://18712242 #define NULL (void*)0 -__attribute__((__nonnull__)) +__attribute__((__nonnull__)) // expected-note 2{{declared 'nonnull' here}} int evil_nonnull_func(int* pointer, void * pv) { if (pointer == NULL) { // expected-warning {{comparison of nonnull parameter 'pointer' equal to a null pointer is 'false' on first encounter}} @@ -105,7 +105,7 @@ } void set_param_to_null(int**); -int another_evil_nonnull_func(int* pointer, char ch, void * pv) __attribute__((nonnull(1, 3))); +int another_evil_nonnull_func(int* pointer, char ch, void * pv) __attribute__((nonnull(1, 3))); // expected-note 2{{declared 'nonnull' here}} int another_evil_nonnull_func(int* pointer, char ch, void * pv) { if (pointer == NULL) { // expected-warning {{comparison of nonnull parameter 'pointer' equal to a null pointer is 'false' on first encounter}} return 0; @@ -127,7 +127,7 @@ extern void FEE(); extern void *pv; -__attribute__((__nonnull__)) +__attribute__((__nonnull__)) // expected-note {{declared 'nonnull' here}} void yet_another_evil_nonnull_func(int* pointer) { while (pv) { @@ -141,7 +141,7 @@ } } -void pr21668_1(__attribute__((nonnull)) const char *p, const char *s) { +void pr21668_1(__attribute__((nonnull)) const char *p, const char *s) { // expected-note {{declared 'nonnull' here}} if (p) // expected-warning {{nonnull parameter 'p' will evaluate to 'true' on first encounter}} ; if (s) // No warning @@ -154,7 +154,7 @@ ; } -__attribute__((returns_nonnull)) void *returns_nonnull_whee(); +__attribute__((returns_nonnull)) void *returns_nonnull_whee(); // expected-note 6{{declared 'returns_nonnull' here}} void returns_nonnull_warning_tests() { if (returns_nonnull_whee() == NULL) {} // expected-warning {{comparison of nonnull function call 'returns_nonnull_whee()' equal to a null pointer is 'false' on first encounter}} Index: lib/Sema/SemaChecking.cpp === --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -8460,21 +8460,23 @@ } } - auto ComplainAboutNonnullParamOrCall = [&](bool IsParam) { + auto ComplainAboutNonnullParamOrCall = [&](const Attr *NonnullAttr) { +bool IsParam = isa(NonnullAttr); std::string Str; llvm::raw_string_ostream S(Str); E->printPretty(S, nullptr, getPrintingPolicy()); unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare : diag::warn_cast_nonnull_to_bool; Diag(E->getExprLoc(), DiagID) << IsParam << S.str() << E->getSourceRange() << Range << IsEqual; +Diag(NonnullAttr->getLocation(), diag::note_declared_nonnull) << IsParam; }; // If we have a CallExpr that is tagged with returns_nonnull, we can complain. if (auto *Call = dyn_cast(E->IgnoreParenImpCasts())) { if (auto *Callee = Call->getDirectCallee()) { - if (Callee->hasAttr()) { -ComplainAboutNonnullParamOrCall(false); + if (const Attr *A = Callee->getAttr()) { +ComplainAboutNonnullParamOrCall(A); return; } } @@ -8496,8 +8498,8 @@ if (const auto* PV = dyn_cast(D)) { if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV)) { - if (PV->hasAttr()) { -ComplainAboutNonnullParamOrCall(true); + if (const Attr *A = PV->getAttr()) { +ComplainAboutNonnullParamOrCall(A); return; } @@ -8508,13 +8510,13 @@ for (const auto *NonNull : FD->specific_attrs()) { if (!NonNull->args_size()) { - ComplainAboutNonnullParamOrCall(true); + ComplainAboutNonnullParamOrCall(NonNull); return; } for (unsigned ArgNo : NonNull->args()) { if (ArgNo == ParamNo) { - ComplainAboutNonnullParamOrCall(true); + ComplainAboutNonnullParamOrCall(NonNull); return; } } Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2933,6 +2933,8 @@ def warn_attribute_nonnull_parm_no_args : Warning< "'nonnull' attribute when used on parameters takes no arguments">, InGroup; +def note_declared_nonnull : Note< + "declared %select{'returns_nonnull'|'nonnull'}0 here">; def warn_attribute_sentinel_named_arguments : Warning<
r272755 - Add a "declared 'nonnull' here" note to warnings where an expression is checked against null.
Author: nicholas Date: Wed Jun 15 00:18:39 2016 New Revision: 272755 URL: http://llvm.org/viewvc/llvm-project?rev=272755&view=rev Log: Add a "declared 'nonnull' here" note to warnings where an expression is checked against null. Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/Sema/nonnull.c Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=272755&r1=272754&r2=272755&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jun 15 00:18:39 2016 @@ -2933,6 +2933,8 @@ def warn_attribute_nonnull_no_pointers : def warn_attribute_nonnull_parm_no_args : Warning< "'nonnull' attribute when used on parameters takes no arguments">, InGroup; +def note_declared_nonnull : Note< + "declared %select{'returns_nonnull'|'nonnull'}0 here">; def warn_attribute_sentinel_named_arguments : Warning< "'sentinel' attribute requires named arguments">, InGroup; Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=272755&r1=272754&r2=272755&view=diff == --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Jun 15 00:18:39 2016 @@ -8460,7 +8460,8 @@ void Sema::DiagnoseAlwaysNonNullPointer( } } - auto ComplainAboutNonnullParamOrCall = [&](bool IsParam) { + auto ComplainAboutNonnullParamOrCall = [&](const Attr *NonnullAttr) { +bool IsParam = isa(NonnullAttr); std::string Str; llvm::raw_string_ostream S(Str); E->printPretty(S, nullptr, getPrintingPolicy()); @@ -8468,13 +8469,14 @@ void Sema::DiagnoseAlwaysNonNullPointer( : diag::warn_cast_nonnull_to_bool; Diag(E->getExprLoc(), DiagID) << IsParam << S.str() << E->getSourceRange() << Range << IsEqual; +Diag(NonnullAttr->getLocation(), diag::note_declared_nonnull) << IsParam; }; // If we have a CallExpr that is tagged with returns_nonnull, we can complain. if (auto *Call = dyn_cast(E->IgnoreParenImpCasts())) { if (auto *Callee = Call->getDirectCallee()) { - if (Callee->hasAttr()) { -ComplainAboutNonnullParamOrCall(false); + if (const Attr *A = Callee->getAttr()) { +ComplainAboutNonnullParamOrCall(A); return; } } @@ -8496,8 +8498,8 @@ void Sema::DiagnoseAlwaysNonNullPointer( if (const auto* PV = dyn_cast(D)) { if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV)) { - if (PV->hasAttr()) { -ComplainAboutNonnullParamOrCall(true); + if (const Attr *A = PV->getAttr()) { +ComplainAboutNonnullParamOrCall(A); return; } @@ -8508,13 +8510,13 @@ void Sema::DiagnoseAlwaysNonNullPointer( for (const auto *NonNull : FD->specific_attrs()) { if (!NonNull->args_size()) { - ComplainAboutNonnullParamOrCall(true); + ComplainAboutNonnullParamOrCall(NonNull); return; } for (unsigned ArgNo : NonNull->args()) { if (ArgNo == ParamNo) { - ComplainAboutNonnullParamOrCall(true); + ComplainAboutNonnullParamOrCall(NonNull); return; } } Modified: cfe/trunk/test/Sema/nonnull.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/nonnull.c?rev=272755&r1=272754&r2=272755&view=diff == --- cfe/trunk/test/Sema/nonnull.c (original) +++ cfe/trunk/test/Sema/nonnull.c Wed Jun 15 00:18:39 2016 @@ -86,7 +86,7 @@ void redecl_test(void *p) { // rdar://18712242 #define NULL (void*)0 -__attribute__((__nonnull__)) +__attribute__((__nonnull__)) // expected-note 2{{declared 'nonnull' here}} int evil_nonnull_func(int* pointer, void * pv) { if (pointer == NULL) { // expected-warning {{comparison of nonnull parameter 'pointer' equal to a null pointer is 'false' on first encounter}} @@ -105,7 +105,7 @@ int evil_nonnull_func(int* pointer, void } void set_param_to_null(int**); -int another_evil_nonnull_func(int* pointer, char ch, void * pv) __attribute__((nonnull(1, 3))); +int another_evil_nonnull_func(int* pointer, char ch, void * pv) __attribute__((nonnull(1, 3))); // expected-note 2{{declared 'nonnull' here}} int another_evil_nonnull_func(int* pointer, char ch, void * pv) { if (pointer == NULL) { // expected-warning {{comparison of nonnull parameter 'pointer' equal to a null pointer is 'false' on first encounter}} return 0; @@ -127,7 +127,7 @@ extern void FOO(); extern void FEE(); extern vo
Re: [PATCH] D21352: Add a "declared 'nonnull' here" note to warnings where an expression is checked against null.
nlewycky closed this revision. nlewycky added a comment. Closed by r272755. http://reviews.llvm.org/D21352 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D15861: Support fully-qualified names for all QualTypes
nlewycky added a subscriber: nlewycky. nlewycky added a comment. (I'm not doing a full review, I just happened to notice a couple things when skimming.) Comment at: lib/Tooling/Core/QualTypeNames.cpp:250 @@ +249,3 @@ +// There are probably other cases ... +if (const TagType *TagDeclType = llvm::dyn_cast_or_null(TypePtr)) + Decl = TagDeclType->getDecl(); s/dyn_cast_or_null/dyn_cast/ You've already checked !TypePtr above, so it can't be null here. Comment at: lib/Tooling/Core/QualTypeNames.cpp:306 @@ +305,3 @@ + // In case of myType& we need to strip the reference first, fully + // qualifiy and attach the reference once again. + if (llvm::isa(QT.getTypePtr())) { s/qualifiy/qualify/ http://reviews.llvm.org/D15861 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: r255371 - Error on redeclaring with a conflicting asm label and on redeclaring with an asm label after the first ODR-use. Detects problems like the one in PR22830 where gcc and clang both compiled
On 01/04/2016 01:40 PM, Kostya Serebryany wrote: On Thu, Dec 17, 2015 at 5:03 PM, Richard Smith mailto:rich...@metafoo.co.uk>> wrote: On Thu, Dec 17, 2015 at 3:59 PM, Nick Lewycky via cfe-commits mailto:cfe-commits@lists.llvm.org>> wrote: On 12/17/2015 10:47 AM, Kostya Serebryany wrote: I am now observing this error message when building glibc with clang (from trunk): ../include/string.h:101:28: error: cannot apply asm label to function after its first use libc_hidden_builtin_proto (memcpy) (many more instances) Do you think this is a bug in glibc code, or the error message could be more relaxed? Could you email me a .i copy of a failing build? That will help me decide whether it's a bug in the error or in glibc. [sorry for delay,] here is the preprocessed source file from glibc: % clang ~/tmp/a.i 2>&1 | grep error: ../include/sys/stat.h:16:28: error: cannot apply asm label to function after its first use ../include/sys/stat.h:17:30: error: cannot apply asm label to function after its first use ../include/sys/stat.h:18:28: error: cannot apply asm label to function after its first use ../include/sys/stat.h:19:30: error: cannot apply asm label to function after its first use ... Also PR22830 comment 1 seems relevant here. Probably, but since this is a very recent regression in clang I thought I should report it. This looks like it's WAI: 3783extern int __fxstat (int __ver, int __fildes, struct stat *__stat_buf) 3784 __attribute__ ((__nothrow__ )) ; ... 3827extern __inline int 3828__attribute__ ((__nothrow__ )) fstat (int __fd, struct stat *__statbuf) 3829{ 3830 return __fxstat (1, __fd, __statbuf); 3831} ... 3910extern __typeof (__fxstat) __fxstat __asm__ ("" "__GI___fxstat") __attribute__ ((visibility ("hidden"))); This is exactly the situation where GCC and Clang will emit a different .o file. Nick On Fri, Dec 11, 2015 at 1:28 PM, Nick Lewycky via cfe-commits mailto:cfe-commits@lists.llvm.org> <mailto:cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>>> wrote: Author: nicholas Date: Fri Dec 11 15:28:55 2015 New Revision: 255371 URL: http://llvm.org/viewvc/llvm-project?rev=255371&view=rev Log: Error on redeclaring with a conflicting asm label and on redeclaring with an asm label after the first ODR-use. Detects problems like the one in PR22830 where gcc and clang both compiled the file but with different behaviour. Added: cfe/trunk/test/Sema/asm-label.c Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=255371&r1=255370&r2=255371&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Dec 11 15:28:55 2015 @@ -4259,6 +4259,9 @@ def err_tag_definition_of_typedef : Erro def err_conflicting_types : Error<"conflicting types for %0">; def err_different_pass_object_size_params : Error< "conflicting pass_object_size attributes on parameters">; +def err_late_asm_label_name : Error< + "cannot apply asm label to %select{variable|function}0 after its first use">; +def err_different_asm_label : Error<"conflicting asm label">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use of %0 with tag type that does not match previous declaration">; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=255371&r1=255370&r2=255371&view=diff ===
Re: [PATCH] D16171: Warning on redeclaring with a conflicting asm label
Weiming Zhao wrote: weimingz created this revision. weimingz added a reviewer: nicholas. weimingz added a subscriber: cfe-commits. r255371 errors on redeclaring with a conflicting asm label. This patch changes errors to warnings to prevent breaking existing codes. Can you include a testcase where the warning is issued but clang and gcc emit the same .o file? http://reviews.llvm.org/D16171 Files: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/Sema/asm-label.c Index: test/Sema/asm-label.c === --- test/Sema/asm-label.c +++ test/Sema/asm-label.c @@ -7,21 +7,21 @@ void f() { g(); } -void g() __asm__("gold"); // expected-error{{cannot apply asm label to function after its first use}} +void g() __asm__("gold"); // expected-warning{{cannot apply asm label to function after its first use}} void h() __asm__("hose"); // expected-note{{previous declaration is here}} -void h() __asm__("hair"); // expected-error{{conflicting asm label}} +void h() __asm__("hair"); // expected-warning{{conflicting asm label}} int x; int x __asm__("xenon"); int y; int test() { return y; } -int y __asm__("yacht"); // expected-error{{cannot apply asm label to variable after its first use}} +int y __asm__("yacht"); // expected-warning{{cannot apply asm label to variable after its first use}} int z __asm__("zebra"); // expected-note{{previous declaration is here}} -int z __asm__("zooms"); // expected-error{{conflicting asm label}} +int z __asm__("zooms"); // expected-warning{{conflicting asm label}} // No diagnostics on the following. Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -2385,13 +2385,13 @@ if (AsmLabelAttr *OldA = Old->getAttr()) { if (OldA->getLabel() != NewA->getLabel()) { // This redeclaration changes __asm__ label. -Diag(New->getLocation(), diag::err_different_asm_label); +Diag(New->getLocation(), diag::warn_different_asm_label); Diag(OldA->getLocation(), diag::note_previous_declaration); } } else if (Old->isUsed()) { // This redeclaration adds an __asm__ label to a declaration that has // already been ODR-used. - Diag(New->getLocation(), diag::err_late_asm_label_name) + Diag(New->getLocation(), diag::warn_late_asm_label_name) << isa(Old)<< New->getAttr()->getRange(); } } Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -4266,9 +4266,11 @@ def err_conflicting_types : Error<"conflicting types for %0">; def err_different_pass_object_size_params : Error< "conflicting pass_object_size attributes on parameters">; -def err_late_asm_label_name : Error< - "cannot apply asm label to %select{variable|function}0 after its first use">; -def err_different_asm_label : Error<"conflicting asm label">; +def warn_late_asm_label_name : Warning< + "cannot apply asm label to %select{variable|function}0 after its first use">, + InGroup; +def warn_different_asm_label : Warning<"conflicting asm label">, + InGroup; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use of %0 with tag type that does not match previous declaration">; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16171: Warning on redeclaring with a conflicting asm label
nicholas added a subscriber: nicholas. nicholas added a comment. Weiming Zhao wrote: > weimingz created this revision. > weimingz added a reviewer: nicholas. > weimingz added a subscriber: cfe-commits. > > r255371 errors on redeclaring with a conflicting asm label. > This patch changes errors to warnings to prevent breaking existing codes. Can you include a testcase where the warning is issued but clang and gcc emit the same .o file? > http://reviews.llvm.org/D16171 > > Files: > > include/clang/Basic/DiagnosticSemaKinds.td > lib/Sema/SemaDecl.cpp > test/Sema/asm-label.c > > Index: test/Sema/asm-label.c > === > > - test/Sema/asm-label.c +++ test/Sema/asm-label.c @@ -7,21 +7,21 @@ void f() > { g(); } -void g() __asm__("gold"); // expected-error{{cannot apply asm > label to function after its first use}} +void g() __asm__("gold"); // > expected-warning{{cannot apply asm label to function after its first use}} > > void h() __asm__("hose"); // expected-note{{previous declaration is here}} > -void h() __asm__("hair"); // expected-error{{conflicting asm label}} +void > h() __asm__("hair"); // expected-warning{{conflicting asm label}} > > int x; int x __asm__("xenon"); int y; > > int test() { return y; } > > -int y __asm__("yacht"); // expected-error{{cannot apply asm label to > variable after its first use}} +int y __asm__("yacht"); // > expected-warning{{cannot apply asm label to variable after its first use}} > > int z __asm__("zebra"); // expected-note{{previous declaration is here}} > -int z __asm__("zooms"); // expected-error{{conflicting asm label}} +int z > __asm__("zooms"); // expected-warning{{conflicting asm label}} > > > > // No diagnostics on the following. > > Index: lib/Sema/SemaDecl.cpp > === > > - lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -2385,13 +2385,13 @@ > if (AsmLabelAttr *OldA = Old->getAttr()) { if (OldA->getLabel() > != NewA->getLabel()) { // This redeclaration changes __asm__ label. > - Diag(New->getLocation(), diag::err_different_asm_label); + > Diag(New->getLocation(), diag::warn_different_asm_label); > Diag(OldA->getLocation(), diag::note_previous_declaration); } } else if > (Old->isUsed()) { // This redeclaration adds an __asm__ label to a > declaration that has // already been ODR-used. > - Diag(New->getLocation(), diag::err_late_asm_label_name) + > Diag(New->getLocation(), diag::warn_late_asm_label_name) << > isa(Old)<< New->getAttr()->getRange(); } } > Index: include/clang/Basic/DiagnosticSemaKinds.td > === > - include/clang/Basic/DiagnosticSemaKinds.td +++ > include/clang/Basic/DiagnosticSemaKinds.td @@ -4266,9 +4266,11 @@ def > err_conflicting_types : Error<"conflicting types for %0">; def > err_different_pass_object_size_params : Error< "conflicting pass_object_size > attributes on parameters">; -def err_late_asm_label_name : Error< > - "cannot apply asm label to %select{variable|function}0 after its first > use">; -def err_different_asm_label : Error<"conflicting asm label">; +def > warn_late_asm_label_name : Warning< + "cannot apply asm label to > %select{variable|function}0 after its first use">, + > InGroup; +def warn_different_asm_label : Warning<"conflicting > asm label">, + InGroup; def err_nested_redefinition : > Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use > of %0 with tag type that does not match previous declaration">; http://reviews.llvm.org/D16171 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16171: Warning on redeclaring with a conflicting asm label
On 14 January 2016 at 10:38, Weiming Zhao via cfe-commits < cfe-commits@lists.llvm.org> wrote: > weimingz added a comment. > > Hi Nick, > > Below is a reduced code: > t.c: > > static long double acoshl (long double __x) __asm__ ("" "acosh") ; // > this is from /arm-linux-gnueabi/libc/usr/include/bits/mathcalls.h > extern long double acoshl (long double) __asm__ ("" "__acoshl_finite") ; > // this is from existing code > > GCC gives warning like: > /tmp/t.c:2:1: warning: asm declaration ignored due to conflict with > previous rename [-Wpragmas] > extern long double acoshl (long double) __asm__ ("" "__acoshl_finite") ; > That's the same case as in this testcase: void foo() __asm__("one"); void foo() __asm__("two"); void test() { foo(); } GCC emits a call to 'one' while Clang emits a call to 'two'. This is a real bug. Please don't downgrade this to a warning. As an alternative, I would accept a patch which changes how clang generates code so that it also produces a call to 'one', with a warning. It looks like what we need to do is drop subsequent asm label declarations on functions that already have one. Nick ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D16171: Warning on redeclaring with a conflicting asm label
On 14 January 2016 at 15:05, Zhao, Weiming wrote: > I agree what you said about different code generated with clang and GCC > generates. In this case, we should throw an error (err_late_asm_label). > > But in this example, there is no use of the function. They are just > redundant declarations and there is no actual code generated. > So I suggest we just give warnings for this case. Otherwise, it will break > existing code like some SPEC benchmarks. > > Please review my 2nd patch. > I think your second patch checks whether it's used at the time of the redeclaration, which is too early. It may be used between there and the end of the program. I expect it not to warn but not error on the testcase I posted in my previous email? To fix, you'd need to store a list of different-asm-label declarations in Sema, check it each time something is ODR-used (see the Sema::Mark<...>Referenced family of calls) to emit the error and remove it from the list. Also, when emitting a PCH or a Module, you need to serialize and deserialize this list. Nick Weiming > > > On 1/14/2016 2:28 PM, Nick Lewycky wrote: > > On 14 January 2016 at 10:38, Weiming Zhao via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> weimingz added a comment. >> >> Hi Nick, >> >> Below is a reduced code: >> t.c: >> >> static long double acoshl (long double __x) __asm__ ("" "acosh") ; // >> this is from /arm-linux-gnueabi/libc/usr/include/bits/mathcalls.h >> extern long double acoshl (long double) __asm__ ("" "__acoshl_finite") >> ; // this is from existing code >> >> GCC gives warning like: >> /tmp/t.c:2:1: warning: asm declaration ignored due to conflict with >> previous rename [-Wpragmas] >> extern long double acoshl (long double) __asm__ ("" "__acoshl_finite") ; >> > > That's the same case as in this testcase: > > void foo() __asm__("one"); > void foo() __asm__("two"); > void test() { foo(); } > > GCC emits a call to 'one' while Clang emits a call to 'two'. This is a > real bug. Please don't downgrade this to a warning. > > As an alternative, I would accept a patch which changes how clang > generates code so that it also produces a call to 'one', with a warning. It > looks like what we need to do is drop subsequent asm label declarations on > functions that already have one. > > Nick > > > ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
PATCH: error on code that redeclares with an __asm__ label after the first ODR use
PR22830 shows a case where some code was adding an __asm__ label after the first use of a function. GCC and Clang diverged on this code, GCC emitting the name in the last __asm__ label for all uses while clang would switch in the middle of the TU as the redeclaration was parsed. The attached patch detects this case and issues an error on such a redeclaration. If this breaks real code, we can turn it down to a warning. Please review! Nick Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td (revision 255303) +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy) @@ -4256,6 +4256,8 @@ def err_conflicting_types : Error<"conflicting types for %0">; def err_different_pass_object_size_params : Error< "conflicting pass_object_size attributes on parameters">; +def err_late_asm_label_name : Error< + "cannot apply asm label to %select{variable|function}0 after its first use">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use of %0 with tag type that does not match previous declaration">; Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp (revision 255303) +++ lib/Sema/SemaDecl.cpp (working copy) @@ -2379,9 +2379,17 @@ if (!Old->hasAttrs() && !New->hasAttrs()) return; - // attributes declared post-definition are currently ignored + // Attributes declared post-definition are currently ignored. checkNewAttributesAfterDef(*this, New, Old); + // Check whether this redeclaration adds an __asm__ label name to a + // declaration that has already been used. + if (Old->isUsed() && !Old->hasAttr() && + New->hasAttr()) { +Diag(New->getLocation(), diag::err_late_asm_label_name) + << isa(Old) << New->getAttr()->getRange(); + } + if (!Old->hasAttrs()) return; Index: test/Sema/asm-label.c === --- test/Sema/asm-label.c (revision 0) +++ test/Sema/asm-label.c (working copy) @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s + +void f(); +void g(); +void f() __asm__("fish"); + +void f() { + g(); +} +void g() __asm__("gold"); // expected-error{{cannot apply asm label to function after its first use}} + +int x; +int y; +int x __asm__("xenon"); + +int test() { return y; } + +int y __asm__("yacht"); // expected-error{{cannot apply asm label to variable after its first use}} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: PATCH: error on code that redeclares with an __asm__ label after the first ODR use
On 10 December 2015 at 17:42, Gao, Yunzhong < yunzhong_...@playstation.sony.com> wrote: > Out of curiosity, is the following test case possible too? > > > > void f(); > > void g() __asm__(“real_g”); // rename g into real_g. > > > > void f() { > > g(); // this would actually be calling real_g() > > } > > void real_g() __asm__("gold"); // re-declaring real_g() into gold <-- > should this be an error too? > I can't see any reason why not. Both clang and gcc will emit "real_g" here instead of "gold", but changing the asm label in a program is highly dubious. I added an error for this too. Thanks! > *From:* cfe-commits [mailto:cfe-commits-boun...@lists.llvm.org] *On > Behalf Of *Nick Lewycky via cfe-commits > *Sent:* Thursday, December 10, 2015 3:15 PM > *To:* Clang Commits > *Subject:* PATCH: error on code that redeclares with an __asm__ label > after the first ODR use > > > > PR22830 shows a case where some code was adding an __asm__ label after the > first use of a function. GCC and Clang diverged on this code, GCC emitting > the name in the last __asm__ label for all uses while clang would switch in > the middle of the TU as the redeclaration was parsed. The attached patch > detects this case and issues an error on such a redeclaration. If this > breaks real code, we can turn it down to a warning. > > > > Please review! > > > > Nick > > > pr22830-2.patch Description: Binary data ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: PATCH: error on code that redeclares with an __asm__ label after the first ODR use
On 11 December 2015 at 12:57, Richard Smith wrote: > On Fri, Dec 11, 2015 at 12:43 PM, Gao, Yunzhong via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> gcc 4.8.2 accepts the following case silently without error or warning: >> >> void f(); >> >> void g() __asm__(“real_g”); >> >> void f() { g(); } // gcc emits a call to real_g() here >> >> void real_g() __asm__(“gold”); >> >> void real_g() { } // gcc generates a body for gold() here >> >> >> >> gcc 4.8.2 generates a warning for the following test case: >> >> void g() __asm__(“func1”); >> >> void g() __asm__(“func2”); // gcc generates a warning and ignores this >> asm label >> >> void g() { } >> >> >> >> Comparing to gcc behavior, I think it is better to emit error in both >> cases. >> > > Why? I don't see anything wrong with the first example. We have a function > whose source-level name is "g()" and whose asm name is "real_g", and we > have a function whose source-level name is "real_g()" and whose asm name is > "gold". What's wrong with that? > Hah, I completely misread the example and fixed something else. What I added an error for is: void f() __asm__("something"); void f() __asm__("somethingelse"); With my patch, we don't issue an error on the case Yunzhong actually supplied. Joerg has pointed out over IRC that this is a really useful construct and that NetBSD's stack smashing protection uses it. We shouldn't break that. I've added a testcase to make sure it continues working. Please review! Nick Looks good to me. Thanks! >> >> - Gao >> >> >> >> >> >> *From:* Nick Lewycky [mailto:nlewy...@google.com] >> *Sent:* Friday, December 11, 2015 12:44 AM >> *To:* Gao, Yunzhong >> *Cc:* Clang Commits >> *Subject:* Re: PATCH: error on code that redeclares with an __asm__ >> label after the first ODR use >> >> >> >> On 10 December 2015 at 17:42, Gao, Yunzhong < >> yunzhong_...@playstation.sony.com> wrote: >> >> Out of curiosity, is the following test case possible too? >> >> >> >> void f(); >> >> void g() __asm__(“real_g”); // rename g into real_g. >> >> >> >> void f() { >> >> g(); // this would actually be calling real_g() >> >> } >> >> void real_g() __asm__("gold"); // re-declaring real_g() into gold <-- >> should this be an error too? >> >> >> >> I can't see any reason why not. Both clang and gcc will emit "real_g" >> here instead of "gold", but changing the asm label in a program is highly >> dubious. I added an error for this too. >> >> >> >> Thanks! >> >> >> >> *From:* cfe-commits [mailto:cfe-commits-boun...@lists.llvm.org] *On >> Behalf Of *Nick Lewycky via cfe-commits >> *Sent:* Thursday, December 10, 2015 3:15 PM >> *To:* Clang Commits >> *Subject:* PATCH: error on code that redeclares with an __asm__ label >> after the first ODR use >> >> >> >> PR22830 shows a case where some code was adding an __asm__ label after >> the first use of a function. GCC and Clang diverged on this code, GCC >> emitting the name in the last __asm__ label for all uses while clang would >> switch in the middle of the TU as the redeclaration was parsed. The >> attached patch detects this case and issues an error on such a >> redeclaration. If this breaks real code, we can turn it down to a warning. >> >> >> >> Please review! >> >> >> >> Nick >> >> >> >> >> >> ___ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> >> > Index: include/clang/Basic/DiagnosticSemaKinds.td === --- include/clang/Basic/DiagnosticSemaKinds.td (revision 255303) +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy) @@ -4256,6 +4256,9 @@ def err_conflicting_types : Error<"conflicting types for %0">; def err_different_pass_object_size_params : Error< "conflicting pass_object_size attributes on parameters">; +def err_late_asm_label_name : Error< + "cannot apply asm label to %select{variable|function}0 after its first use">; +def err_different_asm_label : Error<"conflicting asm label">; def err_ne
r255371 - Error on redeclaring with a conflicting asm label and on redeclaring with an asm label after the first ODR-use. Detects problems like the one in PR22830 where gcc and clang both compiled the
Author: nicholas Date: Fri Dec 11 15:28:55 2015 New Revision: 255371 URL: http://llvm.org/viewvc/llvm-project?rev=255371&view=rev Log: Error on redeclaring with a conflicting asm label and on redeclaring with an asm label after the first ODR-use. Detects problems like the one in PR22830 where gcc and clang both compiled the file but with different behaviour. Added: cfe/trunk/test/Sema/asm-label.c Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=255371&r1=255370&r2=255371&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Dec 11 15:28:55 2015 @@ -4259,6 +4259,9 @@ def err_tag_definition_of_typedef : Erro def err_conflicting_types : Error<"conflicting types for %0">; def err_different_pass_object_size_params : Error< "conflicting pass_object_size attributes on parameters">; +def err_late_asm_label_name : Error< + "cannot apply asm label to %select{variable|function}0 after its first use">; +def err_different_asm_label : Error<"conflicting asm label">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use of %0 with tag type that does not match previous declaration">; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=255371&r1=255370&r2=255371&view=diff == --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 11 15:28:55 2015 @@ -2379,9 +2379,24 @@ void Sema::mergeDeclAttributes(NamedDecl if (!Old->hasAttrs() && !New->hasAttrs()) return; - // attributes declared post-definition are currently ignored + // Attributes declared post-definition are currently ignored. checkNewAttributesAfterDef(*this, New, Old); + if (AsmLabelAttr *NewA = New->getAttr()) { +if (AsmLabelAttr *OldA = Old->getAttr()) { + if (OldA->getLabel() != NewA->getLabel()) { +// This redeclaration changes __asm__ label. +Diag(New->getLocation(), diag::err_different_asm_label); +Diag(OldA->getLocation(), diag::note_previous_declaration); + } +} else if (Old->isUsed()) { + // This redeclaration adds an __asm__ label to a declaration that has + // already been ODR-used. + Diag(New->getLocation(), diag::err_late_asm_label_name) +<< isa(Old) << New->getAttr()->getRange(); +} + } + if (!Old->hasAttrs()) return; Added: cfe/trunk/test/Sema/asm-label.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/asm-label.c?rev=255371&view=auto == --- cfe/trunk/test/Sema/asm-label.c (added) +++ cfe/trunk/test/Sema/asm-label.c Fri Dec 11 15:28:55 2015 @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -verify %s + +void f(); +void f() __asm__("fish"); +void g(); + +void f() { + g(); +} +void g() __asm__("gold"); // expected-error{{cannot apply asm label to function after its first use}} + +void h() __asm__("hose"); // expected-note{{previous declaration is here}} +void h() __asm__("hair"); // expected-error{{conflicting asm label}} + +int x; +int x __asm__("xenon"); +int y; + +int test() { return y; } + +int y __asm__("yacht"); // expected-error{{cannot apply asm label to variable after its first use}} + +int z __asm__("zebra"); // expected-note{{previous declaration is here}} +int z __asm__("zooms"); // expected-error{{conflicting asm label}} + + +// No diagnostics on the following. +void __real_readlink() __asm("readlink"); +void readlink() __asm("__protected_readlink"); +void readlink() { __real_readlink(); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: r255371 - Error on redeclaring with a conflicting asm label and on redeclaring with an asm label after the first ODR-use. Detects problems like the one in PR22830 where gcc and clang both compiled
On 12/17/2015 10:47 AM, Kostya Serebryany wrote: I am now observing this error message when building glibc with clang (from trunk): ../include/string.h:101:28: error: cannot apply asm label to function after its first use libc_hidden_builtin_proto (memcpy) (many more instances) Do you think this is a bug in glibc code, or the error message could be more relaxed? Could you email me a .i copy of a failing build? That will help me decide whether it's a bug in the error or in glibc. On Fri, Dec 11, 2015 at 1:28 PM, Nick Lewycky via cfe-commits mailto:cfe-commits@lists.llvm.org>> wrote: Author: nicholas Date: Fri Dec 11 15:28:55 2015 New Revision: 255371 URL: http://llvm.org/viewvc/llvm-project?rev=255371&view=rev Log: Error on redeclaring with a conflicting asm label and on redeclaring with an asm label after the first ODR-use. Detects problems like the one in PR22830 where gcc and clang both compiled the file but with different behaviour. Added: cfe/trunk/test/Sema/asm-label.c Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=255371&r1=255370&r2=255371&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Dec 11 15:28:55 2015 @@ -4259,6 +4259,9 @@ def err_tag_definition_of_typedef : Erro def err_conflicting_types : Error<"conflicting types for %0">; def err_different_pass_object_size_params : Error< "conflicting pass_object_size attributes on parameters">; +def err_late_asm_label_name : Error< + "cannot apply asm label to %select{variable|function}0 after its first use">; +def err_different_asm_label : Error<"conflicting asm label">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use of %0 with tag type that does not match previous declaration">; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=255371&r1=255370&r2=255371&view=diff == --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 11 15:28:55 2015 @@ -2379,9 +2379,24 @@ void Sema::mergeDeclAttributes(NamedDecl if (!Old->hasAttrs() && !New->hasAttrs()) return; - // attributes declared post-definition are currently ignored + // Attributes declared post-definition are currently ignored. checkNewAttributesAfterDef(*this, New, Old); + if (AsmLabelAttr *NewA = New->getAttr()) { +if (AsmLabelAttr *OldA = Old->getAttr()) { + if (OldA->getLabel() != NewA->getLabel()) { +// This redeclaration changes __asm__ label. +Diag(New->getLocation(), diag::err_different_asm_label); +Diag(OldA->getLocation(), diag::note_previous_declaration); + } +} else if (Old->isUsed()) { + // This redeclaration adds an __asm__ label to a declaration that has + // already been ODR-used. + Diag(New->getLocation(), diag::err_late_asm_label_name) +<< isa(Old) << New->getAttr()->getRange(); +} + } + if (!Old->hasAttrs()) return; Added: cfe/trunk/test/Sema/asm-label.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/asm-label.c?rev=255371&view=auto == --- cfe/trunk/test/Sema/asm-label.c (added) +++ cfe/trunk/test/Sema/asm-label.c Fri Dec 11 15:28:55 2015 @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -verify %s + +void f(); +void f() __asm__("fish"); +void g(); + +void f() { + g(); +} +void g() __asm__("gold"); // expected-error{{cannot apply asm label to function after its first use}} + +void h() __asm__("hose"); // expected-note{{previous declaration is here}} +void h() __asm__("hair"); // expected-error{{conflicting asm label}} + +int x; +int x __asm__("xenon"); +int y; + +int test() { return y; } + +int y __asm__("yacht"); // expected-error{{cannot apply asm label to variable after its first use}} + +int z __asm__("