[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-07-01 Thread Phabricator via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL364867: [analyzer] NFC: CallDescription: Implement 
describing C library functions. (authored by dergachev, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D62556?vs=207406=207431#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62556/new/

https://reviews.llvm.org/D62556

Files:
  cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
  cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
  cfe/trunk/unittests/StaticAnalyzer/CallDescriptionTest.cpp

Index: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
===
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -1044,6 +1044,14 @@
   }
 };
 
+enum CallDescriptionFlags : int {
+  /// Describes a C standard function that is sometimes implemented as a macro
+  /// that expands to a compiler builtin with some __builtin prefix.
+  /// The builtin may as well have a few extra arguments on top of the requested
+  /// number of arguments.
+  CDF_MaybeBuiltin = 1 << 0,
+};
+
 /// This class represents a description of a function call using the number of
 /// arguments and the name of the function.
 class CallDescription {
@@ -1055,6 +1063,7 @@
   // e.g. "{a, b}" represent the qualified names, like "a::b".
   std::vector QualifiedName;
   Optional RequiredArgs;
+  int Flags;
 
 public:
   /// Constructs a CallDescription object.
@@ -1067,9 +1076,15 @@
   /// @param RequiredArgs The number of arguments that is expected to match a
   /// call. Omit this parameter to match every occurrence of call with a given
   /// name regardless the number of arguments.
+  CallDescription(int Flags, ArrayRef QualifiedName,
+  Optional RequiredArgs = None)
+  : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs),
+Flags(Flags) {}
+
+  /// Construct a CallDescription with default flags.
   CallDescription(ArrayRef QualifiedName,
   Optional RequiredArgs = None)
-  : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs) {}
+  : CallDescription(0, QualifiedName, RequiredArgs) {}
 
   /// Get the name of the function that this object matches.
   StringRef getFunctionName() const { return QualifiedName.back(); }
Index: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -356,20 +356,32 @@
   // FIXME: Add ObjC Message support.
   if (getKind() == CE_ObjCMessage)
 return false;
+
+  const IdentifierInfo *II = getCalleeIdentifier();
+  if (!II)
+return false;
+  const FunctionDecl *FD = dyn_cast_or_null(getDecl());
+  if (!FD)
+return false;
+
+  if (CD.Flags & CDF_MaybeBuiltin) {
+return CheckerContext::isCLibraryFunction(FD, CD.getFunctionName()) &&
+   (!CD.RequiredArgs || CD.RequiredArgs <= getNumArgs());
+  }
+
   if (!CD.IsLookupDone) {
 CD.IsLookupDone = true;
 CD.II = ()->getStateManager().getContext().Idents.get(
 CD.getFunctionName());
   }
-  const IdentifierInfo *II = getCalleeIdentifier();
-  if (!II || II != CD.II)
+
+  if (II != CD.II)
 return false;
 
-  const Decl *D = getDecl();
   // If CallDescription provides prefix names, use them to improve matching
   // accuracy.
-  if (CD.QualifiedName.size() > 1 && D) {
-const DeclContext *Ctx = D->getDeclContext();
+  if (CD.QualifiedName.size() > 1 && FD) {
+const DeclContext *Ctx = FD->getDeclContext();
 // See if we'll be able to match them all.
 size_t NumUnmatched = CD.QualifiedName.size() - 1;
 for (; Ctx && isa(Ctx); Ctx = Ctx->getParent()) {
Index: cfe/trunk/unittests/StaticAnalyzer/CallDescriptionTest.cpp
===
--- cfe/trunk/unittests/StaticAnalyzer/CallDescriptionTest.cpp
+++ cfe/trunk/unittests/StaticAnalyzer/CallDescriptionTest.cpp
@@ -143,6 +143,18 @@
   {{{"bar", "foo"}}, false},
   {{"foo"}, true},
   }), "void foo(); struct bar { void foo(); }; void test() { foo(); }"));
+
+  // Test CDF_MaybeBuiltin - a flag that allows matching weird builtins.
+  EXPECT_TRUE(tooling::runToolOnCode(
+  new CallDescriptionAction({
+  {{"memset", 3}, false},
+  {{CDF_MaybeBuiltin, "memset", 3}, true}
+  }),
+  "void foo() {"
+  "  int x;"
+  "  __builtin___memset_chk(, 0, sizeof(x),"
+  " __builtin_object_size(, 0));"
+  "}"));
 }
 
 } // namespace
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-07-01 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ updated this revision to Diff 207406.
NoQ added a comment.

Rebase!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62556/new/

https://reviews.llvm.org/D62556

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
  clang/lib/StaticAnalyzer/Core/CallEvent.cpp
  clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp

Index: clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
===
--- clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
+++ clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
@@ -143,6 +143,18 @@
   {{{"bar", "foo"}}, false},
   {{"foo"}, true},
   }), "void foo(); struct bar { void foo(); }; void test() { foo(); }"));
+
+  // Test CDF_MaybeBuiltin - a flag that allows matching weird builtins.
+  EXPECT_TRUE(tooling::runToolOnCode(
+  new CallDescriptionAction({
+  {{"memset", 3}, false},
+  {{CDF_MaybeBuiltin, "memset", 3}, true}
+  }),
+  "void foo() {"
+  "  int x;"
+  "  __builtin___memset_chk(, 0, sizeof(x),"
+  " __builtin_object_size(, 0));"
+  "}"));
 }
 
 } // namespace
Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -356,20 +356,32 @@
   // FIXME: Add ObjC Message support.
   if (getKind() == CE_ObjCMessage)
 return false;
+
+  const IdentifierInfo *II = getCalleeIdentifier();
+  if (!II)
+return false;
+  const FunctionDecl *FD = dyn_cast_or_null(getDecl());
+  if (!FD)
+return false;
+
+  if (CD.Flags & CDF_MaybeBuiltin) {
+return CheckerContext::isCLibraryFunction(FD, CD.getFunctionName()) &&
+   (!CD.RequiredArgs || CD.RequiredArgs <= getNumArgs());
+  }
+
   if (!CD.IsLookupDone) {
 CD.IsLookupDone = true;
 CD.II = ()->getStateManager().getContext().Idents.get(
 CD.getFunctionName());
   }
-  const IdentifierInfo *II = getCalleeIdentifier();
-  if (!II || II != CD.II)
+
+  if (II != CD.II)
 return false;
 
-  const Decl *D = getDecl();
   // If CallDescription provides prefix names, use them to improve matching
   // accuracy.
-  if (CD.QualifiedName.size() > 1 && D) {
-const DeclContext *Ctx = D->getDeclContext();
+  if (CD.QualifiedName.size() > 1 && FD) {
+const DeclContext *Ctx = FD->getDeclContext();
 // See if we'll be able to match them all.
 size_t NumUnmatched = CD.QualifiedName.size() - 1;
 for (; Ctx && isa(Ctx); Ctx = Ctx->getParent()) {
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
===
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -1044,6 +1044,14 @@
   }
 };
 
+enum CallDescriptionFlags : int {
+  /// Describes a C standard function that is sometimes implemented as a macro
+  /// that expands to a compiler builtin with some __builtin prefix.
+  /// The builtin may as well have a few extra arguments on top of the requested
+  /// number of arguments.
+  CDF_MaybeBuiltin = 1 << 0,
+};
+
 /// This class represents a description of a function call using the number of
 /// arguments and the name of the function.
 class CallDescription {
@@ -1055,6 +1063,7 @@
   // e.g. "{a, b}" represent the qualified names, like "a::b".
   std::vector QualifiedName;
   Optional RequiredArgs;
+  int Flags;
 
 public:
   /// Constructs a CallDescription object.
@@ -1067,9 +1076,15 @@
   /// @param RequiredArgs The number of arguments that is expected to match a
   /// call. Omit this parameter to match every occurrence of call with a given
   /// name regardless the number of arguments.
+  CallDescription(int Flags, ArrayRef QualifiedName,
+  Optional RequiredArgs = None)
+  : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs),
+Flags(Flags) {}
+
+  /// Construct a CallDescription with default flags.
   CallDescription(ArrayRef QualifiedName,
   Optional RequiredArgs = None)
-  : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs) {}
+  : CallDescription(0, QualifiedName, RequiredArgs) {}
 
   /// Get the name of the function that this object matches.
   StringRef getFunctionName() const { return QualifiedName.back(); }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-07-01 Thread Csaba Dabis via Phabricator via cfe-commits
Charusso accepted this revision.
Charusso added a comment.

I have not seen any problem. Thanks!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62556/new/

https://reviews.llvm.org/D62556



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-06-27 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ updated this revision to Diff 206978.
NoQ marked 4 inline comments as done.
NoQ added a comment.

Fxd.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62556/new/

https://reviews.llvm.org/D62556

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
  clang/lib/StaticAnalyzer/Core/CallEvent.cpp
  clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp

Index: clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
===
--- clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
+++ clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
@@ -102,6 +102,16 @@
   {{"foo"}, true},
   }), "void foo(); struct bar { void foo(); }; void test() { foo(); }"));
 
+  EXPECT_TRUE(tooling::runToolOnCode(
+  new CallDescriptionAction({
+  {{"memset", 3}, false},
+  {{CDF_MaybeBuiltin, "memset", 3}, true}
+  }),
+  "void foo() {"
+  "  int x;"
+  "  __builtin___memset_chk(, 0, sizeof(x),"
+  " __builtin_object_size(, 0));"
+  "}"));
 }
 
 } // namespace
Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -356,20 +356,33 @@
   // FIXME: Add ObjC Message support.
   if (getKind() == CE_ObjCMessage)
 return false;
+
+  const IdentifierInfo *II = getCalleeIdentifier();
+  if (!II)
+return false;
+  const FunctionDecl *FD = dyn_cast_or_null(getDecl());
+  if (!FD)
+return false;
+
+  if (CD.Flags & CDF_MaybeBuiltin) {
+return CheckerContext::isCLibraryFunction(FD, CD.getFunctionName()) &&
+   (CD.RequiredArgs == CallDescription::NoArgRequirement ||
+CD.RequiredArgs <= getNumArgs());
+  }
+
   if (!CD.IsLookupDone) {
 CD.IsLookupDone = true;
 CD.II = ()->getStateManager().getContext().Idents.get(
 CD.getFunctionName());
   }
-  const IdentifierInfo *II = getCalleeIdentifier();
-  if (!II || II != CD.II)
+
+  if (II != CD.II)
 return false;
 
-  const Decl *D = getDecl();
   // If CallDescription provides prefix names, use them to improve matching
   // accuracy.
-  if (CD.QualifiedName.size() > 1 && D) {
-const DeclContext *Ctx = D->getDeclContext();
+  if (CD.QualifiedName.size() > 1 && FD) {
+const DeclContext *Ctx = FD->getDeclContext();
 // See if we'll be able to match them all.
 size_t NumUnmatched = CD.QualifiedName.size() - 1;
 for (; Ctx && isa(Ctx); Ctx = Ctx->getParent()) {
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
===
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -1044,6 +1044,14 @@
   }
 };
 
+enum CallDescriptionFlags : int {
+  /// Describes a C standard function that is sometimes implemented as a macro
+  /// that expands to a compiler builtin with some __builtin prefix.
+  /// The builtin may as well have a few extra arguments on top of the requested
+  /// number of arguments.
+  CDF_MaybeBuiltin = 1 << 0,
+};
+
 /// This class represents a description of a function call using the number of
 /// arguments and the name of the function.
 class CallDescription {
@@ -1055,11 +1063,14 @@
   // e.g. "{a, b}" represent the qualified names, like "a::b".
   std::vector QualifiedName;
   unsigned RequiredArgs;
+  int Flags;
 
 public:
   const static unsigned NoArgRequirement = std::numeric_limits::max();
 
   /// Constructs a CallDescription object.
+  /// @param Flags A bitwise-or of CallDescriptionFlags that tweak
+  /// the matching behavior of the CallDescription object.
   ///
   /// @param QualifiedName The list of the name qualifiers of the function that
   /// will be matched. The user is allowed to skip any of the qualifiers.
@@ -1069,9 +1080,15 @@
   /// @param RequiredArgs The number of arguments that is expected to match a
   /// call. Omit this parameter to match every occurrence of call with a given
   /// name regardless the number of arguments.
+  CallDescription(int Flags, ArrayRef QualifiedName,
+  unsigned RequiredArgs = NoArgRequirement)
+  : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs),
+Flags(Flags) {}
+
+  /// Construct a CallDescription with default flags.
   CallDescription(ArrayRef QualifiedName,
   unsigned RequiredArgs = NoArgRequirement)
-  : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs) {}
+  : CallDescription(0, QualifiedName, RequiredArgs) {}
 
   /// Get the name of the function that this object matches.
   StringRef getFunctionName() const { return QualifiedName.back(); }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-06-27 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h:1064
   // e.g. "{a, b}" represent the qualified names, like "a::b".
   std::vector QualifiedName;
   unsigned RequiredArgs;

a_sidorin wrote:
> Not for this review, but why do we have a vector of `const char *`, not 
> StringRefs?
The constructor accepts `ArrayRef` rather than 
`ArrayRef` because `{ "foo", "bar" }` is not a valid initializer for 
`ArrayRef`. The field is the same for simplicity, as converting 
`ArrayRef` to a `vector` is annoying and not really 
useful. See also D51390.



Comment at: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h:1066
   unsigned RequiredArgs;
+  int Flags;
 

a_sidorin wrote:
> Is it a good idea to make Flags a bitfield structure?
This would prevent us from passing the flags into the constructor as `CDF_Foo | 
CDF_Bar` etc.- we'll have to specify every field on every line. I wanted to 
make the initializers as concise as possible to avoid line breaks in code like 
D62557.



Comment at: clang/lib/StaticAnalyzer/Core/CallEvent.cpp:379
+
   if (!II || II != CD.II)
 return false;

a_sidorin wrote:
> `!II` is never false due to the newly-introduced early return.
Right!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62556/new/

https://reviews.llvm.org/D62556



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-06-05 Thread Gábor Horváth via Phabricator via cfe-commits
xazax.hun accepted this revision.
xazax.hun added a comment.
This revision is now accepted and ready to land.

Once Aleksei's comments are resolved it is good to go. My comments are notes 
and not requests.




Comment at: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h:1052
+  /// number of arguments.
+  CDF_MaybeBuiltin = 1 << 0,
+};

I wonder if this is the right name. Do checker authors know the relationship 
between a standard library function and builtins? Maybe something like 
CDF_IsCStandardLibFunc would be more prescriptive when to set this? Or do we 
have non standard library builtins that we might want to match using this 
facility? The comment above is great, I just wonder if checker authors will 
read that. In case it does show up in the doxygen feel free to leave the name 
as is.




Comment at: clang/lib/StaticAnalyzer/Core/CallEvent.cpp:368
+  if (CD.Flags & CDF_MaybeBuiltin) {
+return CheckerContext::isCLibraryFunction(FD, CD.getFunctionName()) &&
+   (CD.RequiredArgs == CallDescription::NoArgRequirement ||

In case this happens to be a performance problem we could cache the builtin id 
in the future. This is just a note, do not need to optimize this prematurely.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62556/new/

https://reviews.llvm.org/D62556



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-06-04 Thread Kristóf Umann via Phabricator via cfe-commits
Szelethus added a comment.

I like the idea, but will need more time to get familiar with `CallEvent` to 
formally accept.

> When matching C standard library functions in the checker, it's easy to 
> forget that they are often implemented as macros that are expanded to 
> compiler builtins. Such builtins would have a different name, so matching the 
> callee identifier would fail, or may sometimes have more arguments than 
> expected (so matching the exact number of arguments would fail, but this is 
> fine as long as we have all the arguments that we need in their respective 
> places.

Just a name an issue that came up recently, in the case of D59812 
, we probably shouldn't need to strip 
`"__builtin_"` off.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62556/new/

https://reviews.llvm.org/D62556



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-06-03 Thread Aleksei Sidorin via Phabricator via cfe-commits
a_sidorin added a comment.

Hi Artem,
Looks mostly good, but I have some comments inline.




Comment at: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h:1064
   // e.g. "{a, b}" represent the qualified names, like "a::b".
   std::vector QualifiedName;
   unsigned RequiredArgs;

Not for this review, but why do we have a vector of `const char *`, not 
StringRefs?



Comment at: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h:1066
   unsigned RequiredArgs;
+  int Flags;
 

Is it a good idea to make Flags a bitfield structure?



Comment at: clang/lib/StaticAnalyzer/Core/CallEvent.cpp:379
+
   if (!II || II != CD.II)
 return false;

`!II` is never false due to the newly-introduced early return.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62556/new/

https://reviews.llvm.org/D62556



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D62556: [analyzer] NFC: CallDescription: Implement describing C library functions.

2019-05-28 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a_sidorin, rnkovacs, 
mikhail.ramalho, Szelethus, baloghadamsoftware, Charusso.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, a.sidorin, szepet.
Herald added a project: clang.
NoQ added a parent revision: D62441: [analyzer] NFC: Introduce a convenient 
CallDescriptionMap class..

When matching C standard library functions in the checker, it's easy to forget 
that they are often implemented as macros that are expanded to compiler 
builtins. Such builtins would have a different name, so matching the callee 
identifier would fail, or may sometimes have more arguments than expected (so 
matching the exact number of arguments would fail, but this is fine as long as 
we have all the arguments that we need in their respective places.

This patch adds a set of flags to the `CallDescription` class so that to handle 
various special matching rules, and adds the first flag into this set, which 
enables a more fuzzy matching for functions that may be implemented as builtins.


Repository:
  rC Clang

https://reviews.llvm.org/D62556

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
  clang/lib/StaticAnalyzer/Core/CallEvent.cpp
  clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp

Index: clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
===
--- clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
+++ clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
@@ -102,6 +102,16 @@
   {{"foo"}, true},
   }), "void foo(); struct bar { void foo(); }; void test() { foo(); }"));
 
+  EXPECT_TRUE(tooling::runToolOnCode(
+  new CallDescriptionAction({
+  {{"memset", 3}, false},
+  {{CDF_MaybeBuiltin, "memset", 3}, true}
+  }),
+  "void foo() {"
+  "  int x;"
+  "  __builtin___memset_chk(, 0, sizeof(x),"
+  " __builtin_object_size(, 0));"
+  "}"));
 }
 
 } // namespace
Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp
===
--- clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -356,20 +356,33 @@
   // FIXME: Add ObjC Message support.
   if (getKind() == CE_ObjCMessage)
 return false;
+
+  const IdentifierInfo *II = getCalleeIdentifier();
+  if (!II)
+return false;
+  const FunctionDecl *FD = dyn_cast_or_null(getDecl());
+  if (!FD)
+return false;
+
+  if (CD.Flags & CDF_MaybeBuiltin) {
+return CheckerContext::isCLibraryFunction(FD, CD.getFunctionName()) &&
+   (CD.RequiredArgs == CallDescription::NoArgRequirement ||
+CD.RequiredArgs <= getNumArgs());
+  }
+
   if (!CD.IsLookupDone) {
 CD.IsLookupDone = true;
 CD.II = ()->getStateManager().getContext().Idents.get(
 CD.getFunctionName());
   }
-  const IdentifierInfo *II = getCalleeIdentifier();
+
   if (!II || II != CD.II)
 return false;
 
-  const Decl *D = getDecl();
   // If CallDescription provides prefix names, use them to improve matching
   // accuracy.
-  if (CD.QualifiedName.size() > 1 && D) {
-const DeclContext *Ctx = D->getDeclContext();
+  if (CD.QualifiedName.size() > 1 && FD) {
+const DeclContext *Ctx = FD->getDeclContext();
 // See if we'll be able to match them all.
 size_t NumUnmatched = CD.QualifiedName.size() - 1;
 for (; Ctx && isa(Ctx); Ctx = Ctx->getParent()) {
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
===
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -1044,6 +1044,14 @@
   }
 };
 
+enum CallDescriptionFlags : int {
+  /// Describes a C standard function that is sometimes implemented as a macro
+  /// that expands to a compiler builtin with some __builtin prefix.
+  /// The builtin may as well have a few extra arguments on top of the requested
+  /// number of arguments.
+  CDF_MaybeBuiltin = 1 << 0,
+};
+
 /// This class represents a description of a function call using the number of
 /// arguments and the name of the function.
 class CallDescription {
@@ -1055,11 +1063,14 @@
   // e.g. "{a, b}" represent the qualified names, like "a::b".
   std::vector QualifiedName;
   unsigned RequiredArgs;
+  int Flags;
 
 public:
   const static unsigned NoArgRequirement = std::numeric_limits::max();
 
   /// Constructs a CallDescription object.
+  /// @param Flags A bitwise-or of CallDescriptionFlags that tweak
+  /// the matching behavior of the CallDescription object.
   ///
   /// @param QualifiedName The list of the name qualifiers of the function that
   /// will be matched. The user is allowed to skip any of the qualifiers.
@@ -1069,9 +1080,15 @@
   /// @param RequiredArgs The number of arguments that is expected to match a
   /// call.