[clang][analyzer] Relax assertion for non-default address spaces in the cstring checker (#153498)

Prevent an assertion failure in the cstring checker when library
functions like memcpy are defined with non-default address spaces.

Adds a test for this case.
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 0e5fc0a..cfc6d34 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1129,9 +1129,9 @@
   if (!ER)
     return true; // cf top comment.
 
-  // FIXME: Does this crash when a non-standard definition
-  // of a library function is encountered?
-  assert(ER->getValueType() == C.getASTContext().CharTy &&
+  // Support library functions defined with non-default address spaces
+  assert(ER->getValueType()->getCanonicalTypeUnqualified() ==
+             C.getASTContext().CharTy &&
          "isFirstBufInBound should only be called with char* ElementRegions");
 
   // Get the size of the array.
diff --git a/clang/test/Analysis/element-region-address-space.c b/clang/test/Analysis/element-region-address-space.c
index dd70662..da59055 100644
--- a/clang/test/Analysis/element-region-address-space.c
+++ b/clang/test/Analysis/element-region-address-space.c
@@ -1,11 +1,27 @@
 // RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown \
-// RUN:   -analyzer-checker=core -verify %s
+// RUN:   -Wno-incompatible-library-redeclaration \
+// RUN:   -analyzer-checker=core,unix -verify %s
 
 // expected-no-diagnostics
 //
 // By default, pointers are 64-bits.
+#define ADDRESS_SPACE_64BITS __attribute__((address_space(0)))
 #define ADDRESS_SPACE_32BITS __attribute__((address_space(3)))
 
 int test(ADDRESS_SPACE_32BITS int *p, ADDRESS_SPACE_32BITS void *q) {
   return p == q; // no-crash
 }
+
+// Make sure that the cstring checker handles non-default address spaces
+ADDRESS_SPACE_64BITS void *
+memcpy(ADDRESS_SPACE_64BITS void *,
+       ADDRESS_SPACE_32BITS const void *,
+       long unsigned int);
+
+ADDRESS_SPACE_64BITS struct {
+  char m[16];
+} n;
+
+void avoid_cstring_checker_crash(ADDRESS_SPACE_32BITS char *p) {
+  memcpy(&n.m[0], p, 4); // no-crash
+}