Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,8 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
auto CallMoveMatcher =
callExpr(callee(functionDecl(hasName("::std::move"))), argumentCountIs(1),
hasArgument(0, declRefExpr().bind("arg")),
anyOf(hasAncestor(lambdaExpr().bind("containing-lambda")),
anyOf(hasAncestor(compoundStmt(
hasParent(lambdaExpr().bind("containing-lambda")))),
hasAncestor(functionDecl().bind("containing-func"))),
unless(inDecltypeOrTemplateArg()),
// try_emplace is a common maybe-moving function that returns a
Expand Down
5 changes: 5 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,11 @@ Changes in existing checks
<clang-tidy/checks/readability-suspicious-call-argument>` related to passing
arguments that refer to program elements without a trivial identifier.

- Fixed a bug in :doc:`bugprone-use-after-move
<clang-tidy/checks/bugprone-use-after-move> where a move in a lambda capture
was treated as if it happened within the body of the lambda, not within the
function that defines the lambda.

Removed checks
^^^^^^^^^^^^^^

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,13 @@ void lambdas() {
auto lambda = [&]() { a.foo(); };
std::move(a);
}
{
A a;
auto lambda = [a = std::move(a)] { a.foo(); };
a.foo();
// CHECK-NOTES: [[@LINE-1]]:5: warning: 'a' used after it was moved
// CHECK-NOTES: [[@LINE-3]]:24: note: move occurred here
}
}

// Use-after-moves are detected in uninstantiated templates if the moved type
Expand Down
12 changes: 9 additions & 3 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6124,9 +6124,6 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
if (!handleTrivialCopy(Info, MD->getParamDecl(0), Args[0], RHSValue,
MD->getParent()->isUnion()))
return false;
if (Info.getLangOpts().CPlusPlus20 && MD->isTrivial() &&
!HandleUnionActiveMemberChange(Info, Args[0], *This))
return false;
if (!handleAssignment(Info, Args[0], *This, MD->getThisType(),
RHSValue))
return false;
Expand Down Expand Up @@ -7638,6 +7635,15 @@ class ExprEvaluatorBase
if (!EvaluateObjectArgument(Info, Args[0], ThisVal))
return false;
This = &ThisVal;

// If this is syntactically a simple assignment using a trivial
// assignment operator, start the lifetimes of union members as needed,
// per C++20 [class.union]5.
if (Info.getLangOpts().CPlusPlus20 && OCE &&
OCE->getOperator() == OO_Equal && MD->isTrivial() &&
!HandleUnionActiveMemberChange(Info, Args[0], ThisVal))
return false;

Args = Args.slice(1);
} else if (MD && MD->isLambdaStaticInvoker()) {
// Map the static invoker for the lambda back to the call operator.
Expand Down
543 changes: 279 additions & 264 deletions clang/lib/Basic/Targets/AVR.cpp

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions clang/lib/Driver/ToolChains/AVR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ using namespace llvm::opt;

namespace {

// NOTE: This list has been synchronized with gcc-avr 5.4.0 and avr-libc 2.0.0.
constexpr struct {
StringRef Name;
StringRef SubPath;
Expand Down Expand Up @@ -88,6 +89,8 @@ constexpr struct {
{"at90usb82", "avr35", "avr35", 0x800100},
{"at90usb162", "avr35", "avr35", 0x800100},
{"ata5505", "avr35", "avr35", 0x800100},
{"ata6617c", "avr35", "avr35", 0x800100},
{"ata664251", "avr35", "avr35", 0x800100},
{"atmega8u2", "avr35", "avr35", 0x800100},
{"atmega16u2", "avr35", "avr35", 0x800100},
{"atmega32u2", "avr35", "avr35", 0x800100},
Expand All @@ -97,6 +100,7 @@ constexpr struct {
{"atmega8a", "avr4", "avr4", 0x800060},
{"ata6285", "avr4", "avr4", 0x800100},
{"ata6286", "avr4", "avr4", 0x800100},
{"ata6612c", "avr4", "avr4", 0x800100},
{"atmega48", "avr4", "avr4", 0x800100},
{"atmega48a", "avr4", "avr4", 0x800100},
{"atmega48pa", "avr4", "avr4", 0x800100},
Expand All @@ -116,8 +120,17 @@ constexpr struct {
{"at90pwm3", "avr4", "avr4", 0x800100},
{"at90pwm3b", "avr4", "avr4", 0x800100},
{"at90pwm81", "avr4", "avr4", 0x800100},
{"ata5702m322", "avr5", "avr5", 0x800200},
{"ata5782", "avr5", "avr5", 0x800200},
{"ata5790", "avr5", "avr5", 0x800100},
{"ata5790n", "avr5", "avr5", 0x800100},
{"ata5791", "avr5", "avr5", 0x800100},
{"ata5795", "avr5", "avr5", 0x800100},
{"ata5831", "avr5", "avr5", 0x800200},
{"ata6613c", "avr5", "avr5", 0x800100},
{"ata6614q", "avr5", "avr5", 0x800100},
{"ata8210", "avr5", "avr5", 0x800200},
{"ata8510", "avr5", "avr5", 0x800200},
{"atmega16", "avr5", "avr5", 0x800060},
{"atmega16a", "avr5", "avr5", 0x800060},
{"atmega161", "avr5", "avr5", 0x800060},
Expand Down Expand Up @@ -192,6 +205,7 @@ constexpr struct {
{"atmega32hvb", "avr5", "avr5", 0x800100},
{"atmega32hvbrevb", "avr5", "avr5", 0x800100},
{"atmega64hve", "avr5", "avr5", 0x800100},
{"atmega64hve2", "avr5", "avr5", 0x800100},
{"at90can32", "avr5", "avr5", 0x800100},
{"at90can64", "avr5", "avr5", 0x800100},
{"at90pwm161", "avr5", "avr5", 0x800100},
Expand Down Expand Up @@ -238,11 +252,14 @@ constexpr struct {
{"atxmega16d4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32a4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32a4u", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32c3", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32c4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32d3", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32d4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32e5", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16e5", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega8e5", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega64a3", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64a3u", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64a4u", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64b1", "avrxmega4", "avrxmega4", 0x802000},
Expand Down
19 changes: 9 additions & 10 deletions clang/lib/Format/BreakableToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ BreakableLineCommentSection::BreakableLineCommentSection(
assert(Tok.is(TT_LineComment) &&
"line comment section must start with a line comment");
FormatToken *LineTok = nullptr;
const int Minimum = Style.SpacesInLineCommentPrefix.Minimum;
// How many spaces we changed in the first line of the section, this will be
// applied in all following lines
int FirstLineSpaceChange = 0;
Expand All @@ -775,7 +776,7 @@ BreakableLineCommentSection::BreakableLineCommentSection(
Lines[i] = Lines[i].ltrim(Blanks);
StringRef IndentPrefix = getLineCommentIndentPrefix(Lines[i], Style);
OriginalPrefix[i] = IndentPrefix;
const unsigned SpacesInPrefix = llvm::count(IndentPrefix, ' ');
const int SpacesInPrefix = llvm::count(IndentPrefix, ' ');

// On the first line of the comment section we calculate how many spaces
// are to be added or removed, all lines after that just get only the
Expand All @@ -784,12 +785,11 @@ BreakableLineCommentSection::BreakableLineCommentSection(
// e.g. from "///" to "//".
if (i == 0 || OriginalPrefix[i].rtrim(Blanks) !=
OriginalPrefix[i - 1].rtrim(Blanks)) {
if (SpacesInPrefix < Style.SpacesInLineCommentPrefix.Minimum &&
Lines[i].size() > IndentPrefix.size() &&
if (SpacesInPrefix < Minimum && Lines[i].size() > IndentPrefix.size() &&
isAlphanumeric(Lines[i][IndentPrefix.size()])) {
FirstLineSpaceChange =
Style.SpacesInLineCommentPrefix.Minimum - SpacesInPrefix;
} else if (SpacesInPrefix > Style.SpacesInLineCommentPrefix.Maximum) {
FirstLineSpaceChange = Minimum - SpacesInPrefix;
} else if (static_cast<unsigned>(SpacesInPrefix) >
Style.SpacesInLineCommentPrefix.Maximum) {
FirstLineSpaceChange =
Style.SpacesInLineCommentPrefix.Maximum - SpacesInPrefix;
} else {
Expand All @@ -800,10 +800,9 @@ BreakableLineCommentSection::BreakableLineCommentSection(
if (Lines[i].size() != IndentPrefix.size()) {
PrefixSpaceChange[i] = FirstLineSpaceChange;

if (SpacesInPrefix + PrefixSpaceChange[i] <
Style.SpacesInLineCommentPrefix.Minimum) {
PrefixSpaceChange[i] += Style.SpacesInLineCommentPrefix.Minimum -
(SpacesInPrefix + PrefixSpaceChange[i]);
if (SpacesInPrefix + PrefixSpaceChange[i] < Minimum) {
PrefixSpaceChange[i] +=
Minimum - (SpacesInPrefix + PrefixSpaceChange[i]);
}

assert(Lines[i].size() > IndentPrefix.size());
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
--Previous) {
Changes[Previous + 1].Spaces -= Shift;
Changes[Previous].Spaces += Shift;
Changes[Previous].StartOfTokenColumn += Shift;
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static const NoteTag *getNoteTag(CheckerContext &C,
bool CastSucceeds, bool IsKnownCast) {
std::string CastToName =
CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString()
: CastToTy->getPointeeCXXRecordDecl()->getNameAsString();
: CastToTy.getAsString();
Object = Object->IgnoreParenImpCasts();

return C.getNoteTag(
Expand Down Expand Up @@ -163,9 +163,9 @@ static const NoteTag *getNoteTag(CheckerContext &C,
bool First = true;
for (QualType CastToTy: CastToTyVec) {
std::string CastToName =
CastToTy->getAsCXXRecordDecl() ?
CastToTy->getAsCXXRecordDecl()->getNameAsString() :
CastToTy->getPointeeCXXRecordDecl()->getNameAsString();
CastToTy->getAsCXXRecordDecl()
? CastToTy->getAsCXXRecordDecl()->getNameAsString()
: CastToTy.getAsString();
Out << ' ' << ((CastToTyVec.size() == 1) ? "not" :
(First ? "neither" : "nor")) << " a '" << CastToName
<< '\'';
Expand Down
59 changes: 44 additions & 15 deletions clang/test/Analysis/cast-value-notes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ using namespace clang;

void evalReferences(const Shape &S) {
const auto &C = dyn_cast<Circle>(S);
// expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
// expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle &'}}
// expected-note@-2 {{Dereference of null pointer}}
// expected-warning@-3 {{Dereference of null pointer}}
}
Expand All @@ -33,25 +33,25 @@ void evalNonNullParamNonNullReturnReference(const Shape &S) {
// expected-note@-1 {{'C' initialized here}}

if (!dyn_cast_or_null<Circle>(C)) {
// expected-note@-1 {{'C' is a 'Circle'}}
// expected-note@-1 {{Assuming 'C' is a 'const class clang::Circle *'}}
// expected-note@-2 {{Taking false branch}}
return;
}

if (dyn_cast_or_null<Triangle>(C)) {
// expected-note@-1 {{Assuming 'C' is not a 'Triangle'}}
// expected-note@-1 {{Assuming 'C' is not a 'const class clang::Triangle *'}}
// expected-note@-2 {{Taking false branch}}
return;
}

if (dyn_cast_or_null<Rectangle>(C)) {
// expected-note@-1 {{Assuming 'C' is not a 'Rectangle'}}
// expected-note@-1 {{Assuming 'C' is not a 'const class clang::Rectangle *'}}
// expected-note@-2 {{Taking false branch}}
return;
}

if (dyn_cast_or_null<Hexagon>(C)) {
// expected-note@-1 {{Assuming 'C' is not a 'Hexagon'}}
// expected-note@-1 {{Assuming 'C' is not a 'const class clang::Hexagon *'}}
// expected-note@-2 {{Taking false branch}}
return;
}
Expand Down Expand Up @@ -87,29 +87,29 @@ void evalNonNullParamNonNullReturnReference(const Shape &S) {

void evalNonNullParamNonNullReturn(const Shape *S) {
const auto *C = cast<Circle>(S);
// expected-note@-1 {{'S' is a 'Circle'}}
// expected-note@-1 {{'S' is a 'const class clang::Circle *'}}
// expected-note@-2 {{'C' initialized here}}

if (!dyn_cast_or_null<Circle>(C)) {
// expected-note@-1 {{'C' is a 'Circle'}}
// expected-note@-1 {{Assuming 'C' is a 'const class clang::Circle *'}}
// expected-note@-2 {{Taking false branch}}
return;
}

if (dyn_cast_or_null<Triangle>(C)) {
// expected-note@-1 {{Assuming 'C' is not a 'Triangle'}}
// expected-note@-1 {{Assuming 'C' is not a 'const class clang::Triangle *'}}
// expected-note@-2 {{Taking false branch}}
return;
}

if (dyn_cast_or_null<Rectangle>(C)) {
// expected-note@-1 {{Assuming 'C' is not a 'Rectangle'}}
// expected-note@-1 {{Assuming 'C' is not a 'const class clang::Rectangle *'}}
// expected-note@-2 {{Taking false branch}}
return;
}

if (dyn_cast_or_null<Hexagon>(C)) {
// expected-note@-1 {{Assuming 'C' is not a 'Hexagon'}}
// expected-note@-1 {{Assuming 'C' is not a 'const class clang::Hexagon *'}}
// expected-note@-2 {{Taking false branch}}
return;
}
Expand Down Expand Up @@ -145,10 +145,10 @@ void evalNonNullParamNonNullReturn(const Shape *S) {

void evalNonNullParamNullReturn(const Shape *S) {
const auto *C = dyn_cast_or_null<Circle>(S);
// expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
// expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle *'}}

if (const auto *T = dyn_cast_or_null<Triangle>(S)) {
// expected-note@-1 {{Assuming 'S' is a 'Triangle'}}
// expected-note@-1 {{Assuming 'S' is a 'const class clang::Triangle *'}}
// expected-note@-2 {{'T' initialized here}}
// expected-note@-3 {{'T' is non-null}}
// expected-note@-4 {{Taking true branch}}
Expand All @@ -172,7 +172,7 @@ void evalNullParamNullReturn(const Shape *S) {

void evalZeroParamNonNullReturnPointer(const Shape *S) {
const auto *C = S->castAs<Circle>();
// expected-note@-1 {{'S' is a 'Circle'}}
// expected-note@-1 {{'S' is a 'const class clang::Circle *'}}
// expected-note@-2 {{'C' initialized here}}

(void)(1 / !C);
Expand All @@ -193,12 +193,12 @@ void evalZeroParamNonNullReturn(const Shape &S) {

void evalZeroParamNullReturn(const Shape *S) {
const auto &C = S->getAs<Circle>();
// expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
// expected-note@-1 {{Assuming 'S' is not a 'const class clang::Circle *'}}
// expected-note@-2 {{Storing null pointer value}}
// expected-note@-3 {{'C' initialized here}}

if (!dyn_cast_or_null<Triangle>(S)) {
// expected-note@-1 {{Assuming 'S' is a 'Triangle'}}
// expected-note@-1 {{Assuming 'S' is a 'const class clang::Triangle *'}}
// expected-note@-2 {{Taking false branch}}
return;
}
Expand All @@ -213,3 +213,32 @@ void evalZeroParamNullReturn(const Shape *S) {
// expected-note@-1 {{Division by zero}}
// expected-warning@-2 {{Division by zero}}
}

// don't crash
// CastValueChecker was using QualType()->getPointeeCXXRecordDecl(), in
// getNoteTag which evaluated to nullptr, then crashed when attempting to
// deref an invocation to getNameAsString(). The fix is to use
// QualType().getAsString().
//
// Example:
// std::string CastToName =
// CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString()
// : CastToTy->getPointeeCXXRecordDecl()->getNameAsString();
// Changed to:
// std::string CastToName =
// CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString()
// : CastToTy.getAsString();
namespace llvm {
template <typename, typename a> void isa(a &);
template <typename> class PointerUnion {
public:
template <typename T> T *getAs() {
(void)isa<int>(*this);
return nullptr;
}
};
class LLVMContext {
PointerUnion<LLVMContext> c;
void d() { c.getAs<int>(); }
};
} // namespace llvm
4 changes: 2 additions & 2 deletions clang/test/Analysis/cast-value-state-dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ using namespace clang;

void evalNonNullParamNonNullReturn(const Shape *S) {
const auto *C = dyn_cast_or_null<Circle>(S);
// expected-note@-1 {{Assuming 'S' is a 'Circle'}}
// expected-note@-1 {{Assuming 'S' is a 'const class clang::Circle *'}}
// expected-note@-2 {{'C' initialized here}}

// FIXME: We assumed that 'S' is a 'Circle' therefore it is not a 'Square'.
if (dyn_cast_or_null<Square>(S)) {
// expected-note@-1 {{Assuming 'S' is not a 'Square'}}
// expected-note@-1 {{Assuming 'S' is not a 'const class clang::Square *'}}
// expected-note@-2 {{Taking false branch}}
return;
}
Expand Down
Loading